*/ public function rules(): array { return [ // Accept email or phone number 'email' => ['required', 'string'], 'password' => ['required', 'string'], ]; } /** * Attempt to authenticate the request's credentials. * Supports login via email or phone number. * * @throws \Illuminate\Validation\ValidationException */ public function authenticate(): void { $this->ensureIsNotRateLimited(); $loginInput = $this->input('email'); $password = $this->input('password'); $remember = $this->boolean('remember'); // Determine if input is email or phone $credentials = $this->resolveCredentials($loginInput, $password); if (! Auth::attempt($credentials, $remember)) { RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages([ 'email' => trans('auth.failed'), ]); } RateLimiter::clear($this->throttleKey()); } /** * Resolve login credentials based on input type (email or phone). */ protected function resolveCredentials(string $loginInput, string $password): array { // Check if input looks like an email if (filter_var($loginInput, FILTER_VALIDATE_EMAIL)) { return [ 'email' => $loginInput, 'password' => $password, ]; } // Normalize phone number (remove dashes, spaces) $phone = preg_replace('/[^0-9]/', '', $loginInput); // Try to find user by phone number in member record $user = User::whereHas('member', function ($query) use ($phone) { $query->where('phone', 'like', "%{$phone}%"); })->first(); if ($user) { return [ 'email' => $user->email, 'password' => $password, ]; } // Fallback: treat as email (will fail auth but proper error message) return [ 'email' => $loginInput, 'password' => $password, ]; } /** * Ensure the login request is not rate limited. * * @throws \Illuminate\Validation\ValidationException */ public function ensureIsNotRateLimited(): void { if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { return; } event(new Lockout($this)); $seconds = RateLimiter::availableIn($this->throttleKey()); throw ValidationException::withMessages([ 'email' => trans('auth.throttle', [ 'seconds' => $seconds, 'minutes' => ceil($seconds / 60), ]), ]); } /** * Get the rate limiting throttle key for the request. */ public function throttleKey(): string { return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip()); } }