User模型expire_date登录验证:需将等于条件改为>=当前日期
Alright, let's get that expiration date check sorted for your user login flow! I see you've already started adding validation in the credentials method, but need to switch from an exact match to checking if expire_date is greater than or equal to today's date.
First, let's clarify: Laravel's default credentials method returns an array of key-value pairs that are used to match against the database with exact equality. So we can't directly use a >= operator there. Instead, we have two clean ways to implement this check:
Option 1: Override validateCredentials in your User Model
This keeps the validation logic tied directly to the User model, which follows Laravel's authentication pattern.
Here's how to modify your User model:
use Illuminate\Auth\Authenticatable; use Illuminate\Database\Eloquent\Model; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Carbon\Carbon; // Use Carbon for better date handling (recommended) class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use Authenticatable, Authorizable, CanResetPassword; // ... Your existing model code (fillable, relationships, etc.) /** * Validate user credentials including expiration date * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(\Illuminate\Contracts\Auth\Authenticatable $user, array $credentials) { // First, check if the password is correct using the parent method if (!parent::validateCredentials($user, $credentials)) { return false; } // Now check if the user's expire_date is >= today's date // Using Carbon ensures we respect your app's timezone settings return $user->expire_date >= Carbon::today(); } }
Option 2: Add the Date Check Directly in Your Login Controller
If you prefer to handle the logic in your controller (more explicit for simple flows), you can adjust the login attempt like this:
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Carbon\Carbon; public function login(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'password' => 'required', ]); $credentials = $request->only('email', 'password'); // Find the user AND check their expiration date in one query $user = User::where('email', $credentials['email']) ->whereDate('expire_date', '>=', Carbon::today()) ->first(); if ($user && Hash::check($credentials['password'], $user->password)) { Auth::login($user); return redirect()->intended('dashboard'); // Redirect to your desired page } // If validation fails, send back an error return back()->withErrors([ 'email' => 'Your credentials are invalid, or your account has expired.', ]); }
Key Notes:
- Timezone Awareness: Using
Carbon::today()is better thandate('Y-m-d')because it respects your app's configured timezone (set inconfig/app.php), avoiding mismatches between server time and your app's intended time. - Why Not Just Modify the Credentials Array? The default authentication provider treats the credentials array as exact matches, so something like
'expire_date' => '>=' . date('Y-m-d')won't work—it'll look for a literal string">=2024-05-20"in the database instead of running a comparison.
内容的提问来源于stack exchange,提问作者misio

