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

如何在Laravel Livewire中智能记录用户组件操作至数据库表

记录Laravel Livewire组件的具体操作到访问日志

问题背景

我通过中间件将用户操作记录到user_access_logs表,常规页面的记录功能正常。但访问包含Laravel Livewire组件的页面时,组件操作(如切换单选框)会被记录为/livewire/update路径。目前已通过中间件过滤该路径,但希望能智能记录Livewire组件的具体操作。

现有代码

初始中间件

<?php

namespace App\Http\Middleware;

use App\Models\UserAccessLog;
use Carbon\Carbon;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class UserAccess
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $user_id = null;
        if (Auth::check()) {
            $user_id = Auth::user()->id;
        }

        $now = Carbon::now()
            ->format('Y-m-d H:i:s');

        UserAccessLog::create([
            UserAccessLog::USER_ID => $user_id,
            UserAccessLog::IP_ADDRESS => $request->ip(),
            UserAccessLog::PATH => $request->path(),
            UserAccessLog::QUERY_STRING => $request->getQueryString(),
            UserAccessLog::DATE_AND_TIME => $now,
        ]);

        return $next($request);
    }
}

过滤/livewire/update后的代码

if ($request->path() !== 'livewire/update') {
    $now = Carbon::now()
        ->format('Y-m-d H:i:s');

    UserAccessLog::create([
        UserAccessLog::USER_ID => $user_id,
        UserAccessLog::IP_ADDRESS => $request->ip(),
        UserAccessLog::PATH => $request->path(),
        UserAccessLog::QUERY_STRING => $request->getQueryString(),
        UserAccessLog::DATE_AND_TIME => $now,
    ]);
}

日志记录示例

常规请求记录

> select * from user_access_logs;
+----+---------+--------------+------+--------------------------------------------------------------+---------------------+
| id | user_id | ip_address   | path | query_string                                                 | date_and_time       |
+----+---------+--------------+------+--------------------------------------------------------------+---------------------+
|  1 | NULL    | 192.168.65.1 | /    | keyword=engineer&philippine_province_ids%5B0%5D=0722&salary= | 2024-03-08 09:23:02 |
+----+---------+--------------+------+--------------------------------------------------------------+---------------------+
1 row in set (0.000 sec)

Livewire请求记录(未过滤时)

|  6 | 9b8367e7-5f0c-414f-972c-ad37f98b7d0b | 192.168.65.1 | dashboard/personnel/applications | NULL         | 2024-03-08 09:37:51 |
|  7 | 9b8367e7-5f0c-414f-972c-ad37f98b7d0b | 192.168.65.1 | livewire/update                  | NULL         | 2024-03-08 09:38:19 |

解决方案

Livewire的/livewire/update请求会携带组件的核心信息,我们可以解析请求payload里的字段,提取组件类名、触发操作、所在页面路径等数据,从而实现智能记录。

步骤1:调整日志表结构(可选但推荐)

如果需要更清晰的记录,建议给user_access_logs表新增以下字段:

  • component:字符串类型,存储Livewire组件的类名
  • action:字符串类型,存储触发的操作方法名
  • payload:文本类型,存储完整的请求数据(可选)

步骤2:修改中间件解析Livewire请求

更新中间件代码,针对/livewire/update请求做特殊处理:

<?php

namespace App\Http\Middleware;

use App\Models\UserAccessLog;
use Carbon\Carbon;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class UserAccess
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $user_id = Auth::check() ? Auth::user()->id : null;
        $now = Carbon::now()->format('Y-m-d H:i:s');

        if ($request->path() === 'livewire/update') {
            // 解析Livewire请求的核心数据
            $fingerprint = $request->input('fingerprint', []);
            $serverMemo = $request->input('serverMemo', []);
            
            // 提取组件类名和所在页面路径
            $componentClass = $fingerprint['class'] ?? 'UnknownComponent';
            $pagePath = $fingerprint['path'] ?? '/livewire/update';
            
            // 提取触发的操作方法(支持单个action场景)
            $action = !empty($serverMemo['actions']) ? $serverMemo['actions'][0]['method'] : 'UnknownAction';
            
            // 记录Livewire操作
            UserAccessLog::create([
                UserAccessLog::USER_ID => $user_id,
                UserAccessLog::IP_ADDRESS => $request->ip(),
                UserAccessLog::PATH => $pagePath, // 记录组件所在的页面路径,而非统一的/livewire/update
                UserAccessLog::QUERY_STRING => $request->getQueryString(),
                UserAccessLog::DATE_AND_TIME => $now,
                'component' => $componentClass,
                'action' => $action,
                'payload' => json_encode($request->all()) // 可选:存储完整请求数据用于排查
            ]);
        } else {
            // 常规请求的原有记录逻辑
            UserAccessLog::create([
                UserAccessLog::USER_ID => $user_id,
                UserAccessLog::IP_ADDRESS => $request->ip(),
                UserAccessLog::PATH => $request->path(),
                UserAccessLog::QUERY_STRING => $request->getQueryString(),
                UserAccessLog::DATE_AND_TIME => $now,
            ]);
        }

        return $next($request);
    }
}

关键说明

  • 从fingerprint字段获取组件类名和所在页面路径,让日志能关联到具体页面,而非模糊的/livewire/update
  • 从serverMemo.actions数组提取触发的方法名,比如切换单选框时,Livewire会自动触发updatedXXX方法(XXX为组件属性名)
  • 如果不需要新增表字段,可以把组件信息拼接在PATH字段中,格式示例:dashboard/personnel/applications - 组件: App\Livewire\PersonnelApp - 操作: updatedStatus

注意事项

  • Livewire的更新请求均为POST方法,无需处理GET场景
  • 若存在多个连续action的情况,可循环遍历serverMemo.actions数组,分别记录每个操作
  • 可以根据业务需求过滤掉某些无需记录的操作(比如自动触发的updated类方法)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:36:18