You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel中记录用户登出时间至数据库

在Laravel中记录用户登出时间的两种常用方案

首先确保你的用户表(默认是users)有logout_at字段,如果没有,先创建迁移:

php artisan make:migration add_logout_at_to_users_table --table=users

然后在生成的迁移文件中添加字段定义:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->timestamp('logout_at')->nullable();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('logout_at');
    });
}

执行迁移生效:

php artisan migrate

方案一:监听Laravel自带的Logout事件

Laravel在用户主动登出时会触发Illuminate\Auth\Events\Logout事件,通过监听这个事件可以自动记录登出时间:

  1. 生成事件监听器:
php artisan make:listener LogLogoutTime --event=Illuminate\Auth\Events\Logout
  1. 打开生成的app/Listeners/LogLogoutTime.php,修改handle方法:
public function handle(Logout $event)
{
    // $event->user 即为当前登出的用户实例
    $event->user->update([
        'logout_at' => now()
    ]);
}
  1. 在app/Providers/EventServiceProvider.php的$listen数组中注册事件与监听器的关联:
protected $listen = [
    // 保留其他已注册事件
    \Illuminate\Auth\Events\Logout::class => [
        \App\Listeners\LogLogoutTime::class,
    ],
];

完成后,用户每次主动登出时,系统会自动更新logout_at字段。


方案二:重写Auth控制器的登出方法

如果你不想用事件监听,也可以直接重写Auth控制器的登出逻辑:

Laravel 8+ 版本(对应AuthenticatedSessionController)

use Illuminate\Http\Request;

public function destroy(Request $request)
{
    // 先获取用户实例,登出后无法再通过auth()->user()获取
    $user = $request->user();
    
    // 执行框架默认的登出逻辑
    $this->guard()->logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();
    
    // 更新登出时间
    if ($user) {
        $user->update([
            'logout_at' => now()
        ]);
    }
    
    return redirect('/');
}

Laravel 5.x/6.x 版本(对应LoginController)

use Illuminate\Http\Request;

public function logout(Request $request)
{
    $user = $request->user();
    
    $this->guard()->logout();
    $request->session()->invalidate();
    
    if ($user) {
        $user->update([
            'logout_at' => now()
        ]);
    }
    
    return redirect('/');
}

额外说明:处理会话自动过期的情况

上面的方案仅覆盖用户主动登出的场景,如果需要记录会话自动过期的时间,可以通过中间件实现近似记录:

  1. 生成中间件:
php artisan make:middleware RecordSessionExpiry
  1. 在中间件的handle方法中添加逻辑:
use Carbon\Carbon;

public function handle(Request $request, Closure $next)
{
    $response = $next($request);
    
    // 检查用户已认证且会话已过期
    if (auth()->check() && $request->session()->has('last_activity')) {
        $lastActivity = Carbon::parse($request->session()->get('last_activity'));
        if (now()->diffInMinutes($lastActivity) >= config('session.lifetime')) {
            auth()->user()->update([
                'logout_at' => now()
            ]);
        }
    }
    
    // 更新用户最后活跃时间
    $request->session()->put('last_activity', now());
    
    return $response;
}
  1. 在app/Http/Kernel.php的web中间件组中注册该中间件:
protected $middlewareGroups = [
    'web' => [
        // 保留其他已注册中间件
        \App\Http\Middleware\RecordSessionExpiry::class,
    ],
];

注意:这种方式是基于用户最后一次请求的时间推算过期时间,记录的时间会和实际过期时间有微小偏差。

内容的提问来源于stack exchange,提问作者archibaldenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:41:04