Laravel 8 中推荐用模型观察者自动记录数据变更,需创建 OperationLog 模型及迁移表,定义 user_id、action_type、model_name 等字段,为指定模型生成并注册观察者,重写 created/updated/deleted/restored 方法,通过 getChanges() 获取真实改动,注意操作人获取、关闭日志模型时间戳、避免递归操作,并可选结合队列异步落库。

在 Laravel 8 中,用模型观察者(Observer)实现数据变更的自动记录是最推荐、最稳定的方式。它不依赖第三方包,不侵入模型逻辑,能精准捕获真实改动,且天然支持软删除、恢复等全生命周期事件。
创建日志模型与迁移表
先建一张专门存操作日志的表:
- 运行命令生成模型和迁移:php artisan make:model OperationLog -m
- 编辑生成的迁移文件,在 up() 方法中添加字段:
user_id(操作人)、action_type(如 created/updated/deleted)、model_name(如 App\Models\Post)、record_id(被操作记录 ID)、changes(JSON,存变动字段)、ip_address、user_agent - 执行 php artisan migrate 创建数据表
生成并注册模型观察者
为需要监听的模型(比如 User 或 Post)创建观察者:
- 命令生成:php artisan make:observer PostObserver --model=Post
- 在生成的 PostObserver.php 中,重写 created、updated、deleted、restored 四个方法
- 每个方法里调用
$model->getChanges()获取真实修改字段,避免记录未变的脏数据 - 在 AppServiceProvider 的 boot() 方法中注册:
Post::observe(PostObserver::class);
记录逻辑要避开常见坑
在观察者方法内写日志时,注意这些关键点:
- 从
auth()->id()或$request->user()?->id取操作人,别用 session 或 token 解析,防止队列或命令行场景丢失上下文 - 日志模型建议关闭时间戳:
public $timestamps = false;,自己控制created_at字段,避免和主事务时间错位 - 不要在观察者里调用
$model->save()或触发其他模型操作,否则可能引发递归监听或事务异常 - 批量更新(如
Post::where(...)->update(...))不会触发观察者事件,这是 Eloquent 层级限制,需另做处理
可选:配合队列异步落库
如果日志量大或写入较慢,可让日志记录走队列,不影响主流程响应:
- 让观察者中的日志写入逻辑封装进一个 Job 类:php artisan make:job LogOperation
- Job 类实现 ShouldQueue 接口,并在 handle() 中执行日志保存
- 观察者中直接分发:
LogOperation::dispatch($model, 'updated', $changes); - 确保队列服务已配置并运行:php artisan queue:work


















