Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

aadenfr's avatar

Detect days remaining before ending date

Hello im working on project , and i add password_changed_at to enforce user change his password after 30 days , but also i want send an email as notfiction to informe him is stay 5 , 3 or 1 day to update your password else it will enforced automatically to update his password after 30 day.

my problem is finding the best why to calculate if remaining is x day'q to send message . here is my try using middleware:

public function handle(Request $request, Closure $next): Response
{
    $user = $request->user();
    $passwordChangedAt = new Carbon(($user->password_changed_at) ?: $user->created_at);
    $startDate=$passwordChangedAt;
    $endDate = $startDate->addDays(25);
    dump("1 ".$startDate);
    dump("2 ".$endDate);
    dump( Carbon::now()->diffInDays($endDate) );
    die();

	//todo:: send email is remaining is 5 day
	if(Carbon::now()->diffInDays($endDate) ==5 ){ // this tested but i want best soluation
		// code here ....
	}

    if (Carbon::now()->diffInDays($passwordChangedAt) >= 30) {
		// this works 100%
        return redirect()->route('auth.expired.password.show');
    }
    return $next($request);
}```

0 likes
5 replies
Snapey's avatar

use a scheduled job, not middleware.

//get collection of users whose password was last changed more than 25 days ago
$users = User::whereDate('password_changed_at', '<', today()->subdays(25)->get();

1 like
aadenfr's avatar

@Snapey thanks for answring my question... but what about make it as an event in login controller ... i will check each user status when try login if his password will expiry i will send the email. scheduled job => will send an email for all users right !

Snapey's avatar

@aadenfr why send an email when they are logging in? Just show the message there in the web page?

what happens if they don't visit the site at all? next time they come their password is already expired?

1 like
aadenfr's avatar

@Snapey this make sense!, scheduled job is right solution for this now thanks @snapey i appreciate you explanation.

martinbean's avatar
Level 80

@aadenfr You should be scheduling different jobs for different days remaining values. Given that only the days value is changing I’d create a single, re-usable command that you can schedule with arbitrary day values:

class SendPasswordExpirationEmail extends Command
{
    protected $signature = 'password:expire-email {--days=}';

    public function handle(): int
    {
        $days = (int) $this->option('days');

        if ($days < 1) {
            throw new InvalidArgumentException(
                sprintf('Days [%s] is not a positive integer', $days)
            );
        }

        $users = User::query()->passwordExpiresInDays($days)->get();

        $users->each(function (User $user) use ($days) {
            Mail::to($user)->queue(new PasswordExpirationEmail($days));
        });
    }
}

You can then schedule multiple instances of this command:

$schedule->command('password:expire-email --days=1');
$schedule->command('password:expire-email --days=5');
$schedule->command('password:expire-email --days=7');
1 like

Please or to participate in this conversation.