activity() 默认不记录 http 请求等非模型操作,需手动调用或配合中间件;支持causedby()、withproperties()等链式方法,但仅对eloquent操作生效,异步需自定义activitylogger并注意序列化限制。

activity() 默认只记录模型变更,不自动捕获 HTTP 请求行为。想记录“用户访问了哪个页面”“点击了什么按钮”,得手动调用或配合中间件/事件。
如何让 activity() 记录非模型操作(如登录、跳转、API 调用)
它不是 Laravel 原生日志,不监听请求生命周期;activity() 是一个服务定位器式门面,只在你显式调用时才写入数据库。
- 直接使用
activity()->log('用户导出订单报表'),描述必须是字符串,不支持自动填充上下文 - 可链式添加操作者:
activity()->causedBy($user)->log('修改了系统配置'),但$user必须是 Eloquent 模型实例(不能是数组或 ID) - 附加结构化数据要用
withProperties():activity()->withProperties(['order_count' => 12])->log('批量导出完成') - 别在循环里高频调用——默认同步写库,没开队列时会拖慢响应
LogsActivity trait 的字段控制为什么有时失效
常见现象:改了 $logAttributes,但日志里仍出现 password 字段;或者设置了 $logOnlyDirty = true,却还是记了没变的字段。
- trait 仅对 Eloquent 的
save()、update()、delete()生效,不拦截DB::table()->update()或原生 SQL -
$logAttributesToIgnore和logExcept()优先级不同:前者是静态数组,后者在getActivitylogOptions()中定义,后者更高 - 如果模型用了
casts(比如'status' => 'boolean'),且变更前后值在 PHP 层被转成相同类型(0↔false),dirty 检测可能误判 - 软删除模型中,
forceDelete()不触发 trait 日志,需单独处理
多日志通道(log_name)的实际隔离效果
activity('admin-actions') 和 activity('user-profile') 写入的是同一张 activity_log 表,只是 log_name 字段值不同。这不是物理隔离,而是逻辑分组。
- 查询时必须加
where('log_name', 'admin-actions'),否则Activity::all()会混在一起 - 迁移不会为每个 log_name 创建新表;自定义表名需重写
Activity模型的$table属性,并确保所有调用都指向它 - 配置文件里的
default_log_name只影响未指定名称的activity()调用,不影响 trait 行为(trait 用的是模型自身的$logName)
异步记录 activity 日志的最小可行配置
开队列不是加个 ShouldQueue 就行——activity() 门面本身不支持延迟,必须替换底层保存逻辑。
- 最简方案:在
config/activitylog.php中设'use_database_transactions' => false,并确保队列驱动可用 - 真正生效要靠自定义
ActivityLogger实现:重写log()方法,把$activity->save()替换为LogActivityJob::dispatch(...) - 注意 job 序列化:
$activity->subject(如 User 模型)会被序列化,若含大量关联或闭包会失败,建议只传 ID 和必要字段 - 批量日志(
LogBatch::startBatch())无法跨队列任务保持batch_uuid,因为批次状态存在内存里,异步后就丢了
log_name 和 causer_type/causer_id 加索引——这些都不是开箱即用的。











