observer不触发的首要原因是注册失败,必须手动在appserviceprovider::boot()中调用model::observe(observer类),且类名须严格匹配模型名+observer后缀;saving在事务内可修改属性或中断保存,saved在提交后执行适合发通知;批量操作如update()、upsert()不触发observer;软删除触发deleting/deleted,硬删才触发forcedeleting/forcedeleted。

Observer 不触发?先查注册和类名是否严格匹配
Observer 类写好了但事件完全没反应,90% 是注册环节出问题。Laravel 从不自动扫描 app/Observers/ 目录,UserObserver 文件存在 ≠ 它会生效。
必须手动在 AppServiceProvider::boot() 中调用 User::observe(UserObserver::class);如果模型叫 Post,Observer 类名必须是 PostObserver,少一个字母或大小写错都会反射失败。
常见错误包括:
- 把注册逻辑误放在
EventServiceProvider::$listen里 —— 那是给事件系统(Event::dispatch())用的,和 Observer 无关 - 注册时机太早,在模型类还没加载完时就调
Model::observe(),导致绑定失败 - 用了 Laravel 10+ 却还在
boot()里写监听逻辑 —— 此时模型尚未实例化,static::created()等根本不会注册
saving 和 saved 的事务行为差异极大,选错会导致数据不一致
saving 在事务内、INSERT/UPDATE 执行前触发,可修改属性值或返回 false 中断保存(比如校验手机号格式);saved 则在事务已提交、数据落库后才执行,适合发通知、写审计日志、推队列任务。
关键区别:
- 在
saving回调里调$model->save()会递归触发自身,极易栈溢出 - 在
saved回调里改字段再save(),不会写回数据库(已提交) -
updated()只在字段真实变更($model->isDirty()为 true)时触发;saved()对 insert 和 update 都触发
批量操作(update()、upsert()、DB::table())完全不走 Observer
Eloquent Observer 只监听通过模型实例调用的 save()、create()、delete() 等方法。所有绕过模型生命周期的操作,Observer 一概不知。
例如:
-
User::where('status', 'pending')->update(['status' => 'active'])—— 不触发任何 Observer 方法 -
DB::table('users')->increment('login_count')—— 同样无响应 -
User::upsert([...], ['email'], ['name'])—— 不触发creating/created
若业务强依赖“批量变更后做某事”,只能两种方案:一是改用循环 + 模型实例 save()(注意 N+1 问题);二是业务层显式调用自定义方法,别指望 Observer 自动兜底。
软删除 vs 硬删除:事件钩子名只差一个字母,但语义完全不同
软删除(delete())走的是 deleting → deleted 流程;硬删(forceDelete())才触发 forceDeleting → forceDeleted。漏掉 force 前缀,监听就会失效。
典型场景:
- 用户回收站清空时需彻底擦除敏感字段 —— 必须监听
forceDeleting,而非deleting - 软删除后同步更新统计报表 —— 用
deleted即可,它在deleted_at写入后触发 -
restoring和restored仅在调用restore()时触发,forceDeleted后无法恢复
Observer 里写错一个字母,整个逻辑就静默失效 —— 这是最容易被忽略、也最难 debug 的点。











