Laravel登录验证:如何在比较前转换数据库邮箱值为小写?
Great question! You’ve already nailed converting the user’s input email to lowercase in the credentials method—that’s a solid first step. To make the database-side email match regardless of its stored case, you’ve got two reliable approaches: one for immediate query-time matching, and a better long-term fix that standardizes your data for good:
1. Match by converting stored emails to lowercase during authentication
If you can’t modify existing database data right now, you can adjust the authentication logic to convert the stored email to lowercase on the fly when checking credentials.
Option A: Override the attemptLogin method
Update your LoginController to build a custom query that uses the database’s LOWER() function to compare emails:
protected function attemptLogin(Request $request) { $credentials = $this->credentials($request); // Fetch the user by matching the lowercase version of their stored email $user = $this->guard()->getProvider()->retrieveByCredentials([ \DB::raw('LOWER('.$this->username().')') => $credentials[$this->username()], ]); if (!$user) { $this->fireFailedEvent($request, null); return false; } // Validate password and handle "remember me" return $this->guard()->login($user, $request->filled('remember')); }
Option B: Override the validateCredentials method
Alternatively, you can directly compare the lowercase stored email to your already-lowercased input:
use Illuminate\Contracts\Auth\Authenticatable as UserContract; protected function validateCredentials(UserContract $user, array $credentials) { $plainPassword = $credentials['password']; // Compare lowercase stored email to lowercase input email return strtolower($user->getAuthIdentifier()) === $credentials[$this->username()] && $this->hasher->check($plainPassword, $user->getAuthPassword()); }
2. Standardize stored emails to lowercase (Recommended)
The cleaner, more efficient long-term fix is to ensure all emails are stored in lowercase from the start. This eliminates runtime conversions and prevents duplicate accounts (e.g., MyName@email.com and myname@email.com being treated as separate users).
Step 1: Add an attribute mutator to your User model
Add a mutator to automatically convert emails to lowercase whenever they’re set (during registration, profile updates, etc.):
// app/Models/User.php public function setEmailAttribute($value) { $this->attributes['email'] = strtolower(trim($value)); }
Step 2: Update existing database emails to lowercase
Run a one-time query to convert all existing mixed-case emails to lowercase. You can do this via a migration or Artisan tinker:
// Via a migration file: public function up() { \DB::statement('UPDATE users SET email = LOWER(email)'); } // Or via Artisan tinker (run `php artisan tinker` first): // User::query()->update(['email' => \DB::raw('LOWER(email)')]);
Step 3: Optional: Add database-level constraints (Laravel 9+)
For extra safety, enforce lowercase storage at the database level using Laravel’s lowercase() column modifier:
Schema::table('users', function (Blueprint $table) { $table->string('email')->unique()->lowercase()->change(); });
内容的提问来源于stack exchange,提问作者Jonatan Uran

