observer必须手动注册,不注册等于没写;需在appserviceprovider::boot()中use模型和观察者类后调用model::observe(observer::class),方法名须严格小写且仅接收模型实例。

Observer 必须手动注册,不注册等于没写
Laravel 5.5 的模型观察者不会自动加载或绑定,哪怕你用 php artisan make:observer UserObserver --model=User 生成了类,放在 app/Observers/ 下,方法名也全小写对得上(如 created、updated),只要没注册,就完全不会触发。
常见错误现象:日志没输出、断点不进、created() 方法像不存在一样。根本原因就是漏了这一步。
- 推荐在
AppServiceProvider::boot()中注册:use App\Models\User; use App\Observers\UserObserver;,然后调用User::observe(UserObserver::class) - 注册语句必须放在
parent::boot();之后,否则模型类可能未加载,调用静默失败 - 不要把
observe()写在模型自己的boot()里——5.5 不支持booted(),且容易和事件监听器冲突 - 若一个观察者要监听多个模型,需分别调用:
User::observe(...)、Post::observe(...),不能传数组
creating 和 created 触发时机完全不同
这两个钩子名字只差一个字母,但执行阶段和可用数据差异极大,选错会导致逻辑失败或死循环。
creating 在 INSERT SQL 执行前触发,此时 $model->id 还是 null,可以修改属性、抛异常中断保存;created 在 INSERT 成功后、事务提交前触发,$model->id 已生成,但不能再改模型属性(改了也不会入库)。
- 想拦截非法创建(如邮箱重复)、设置默认值(
$model->status = 'pending'),用creating - 想发邮件、写日志、更新缓存,优先用
created,但注意事务未提交时其他请求查不到这条记录 - 别在
created里调$model->save()—— 会再次触发saved,最终栈溢出 -
updating只响应模型实例的save()或update(),不响应User::where(...)->update(...)这类批量操作
方法名必须严格小写,且只接收模型实例
Laravel 5.5 通过反射调用观察者方法,不支持任何参数扩展或命名变体。方法签名错一个字符,整个监听就失效。
正确写法:public function created(User $user) { ... };错误写法包括:Created、onCreated、created(User $user, $event)、created($user)(类型提示缺失)。
- 支持的事件名共 10 个:
retrieved、creating、created、updating、updated、saving、saved、deleting、deleted、restoring(软删除恢复) -
retrieved每次查询都会触发(get()、first()、paginate()中每条记录都算一次),滥用会导致 N+1 性能问题 - 所有方法只接收一个参数:模型实例本身,原始数据需用
$user->getOriginal('email')获取,不能依赖传入的 ID 或数组 - 软删除场景下,
delete()触发的是deleting/deleted,只有forceDelete()才走forceDeleting/forceDeleted
调试时最容易忽略的两个硬限制
5.5 版本没有 event:discover 自动扫描机制,也没有 $observe 属性集中注册,所有绑定都靠显式调用 observe()。这意味着一旦注册位置不对或类未加载,就彻底静默失效,没有任何报错提示。
- 确保
AppServiceProvider在config/app.php的providers数组中已启用(默认有) - 注册前务必
use模型和观察者类,避免因自动加载延迟导致Class 'User' not found静默失败 - 测试时清空配置缓存:
php artisan config:clear,否则旧注册可能残留 - 观察者里禁止发起 HTTP 请求或嵌套事务——5.5 对事务边界控制较弱,容易引发超时或死锁











