Laravel怎么开启并使用观察者 _ Laravel Observer模型监听方法【经验】

5次阅读

observer未触发的首要原因是未注册,需在appserviceprovider::boot()中调用model::observe(observerclass::class);其次注意created()与saved()等事件触发时机差异,避免逻辑错误或死循环

Laravel怎么开启并使用观察者 _ Laravel Observer模型监听方法【经验】

Observer类没被触发?先确认是否已注册

laravel的Observer不会自动生效,必须手动注册到模型上,这是最常被跳过的一步。不注册就监听不到任何事件,代码写得再全也没用。

  • AppServiceProvider::boot() 里调用 Model::observe(ObserverClass::class),比如 User::observe(UserObserver::class)
  • 也可以在模型自身的 boot() 方法里注册,但不推荐——耦合高、不易测试、批量注册时难管理
  • 如果用了 Laravel 10+ 的自动发现(php artisan Event:discover),需确保 EventServiceProvider 中启用了 $listen 自动扫描,并且 Observer 类命名和路径符合约定(如 AppObserversUserObserver

created() 和 saved() 行为不同,别混用

created() 只在 INSERT 成功后触发,而 saved() 在 INSERT 和 UPDATE 后都会触发。选错会导致逻辑重复执行或漏执行。

  • 需要“仅首次创建时发通知”,用 created();要“每次保存都更新缓存”,用 saved()
  • updated()saved() 不是互斥关系:一次 update 操作会先触发 updated(),再触发 saved()
  • 注意:软删除场景下,deleted()forceDeleted() 是分开的,delete() 默认只软删,不会进 forceDeleted()

Observer里不能直接改模型属性再 save(),会死循环

saving()updating() 里调用 $model->save(),会再次触发相同事件,最终爆或超时。

  • 想修改字段值,直接赋值即可:$model->slug = Str::slug($model->name),Laravel 会在后续流程中自动保存
  • 如果必须触发另一次保存(比如级联更新关联模型),改用 DB::transaction() + 原生查询,或把逻辑抽到 service 层,在 observer 外调用
  • 调试时可在 observer 方法开头加 Log::debug('user saving', ['id' => $model->id]),快速确认是否重复进入

队列化 Observer 要小心事务边界

Observer 方法默认同步执行,一旦开启队列(比如用 dispatch(new UpdateSearchIndex($model))),可能遇到模型数据已变或事务未提交的问题。

  • 不要在 observer 里 dispatch 依赖当前模型完整状态的任务,除非你明确处理了延迟消费时的数据一致性
  • 更稳妥的做法:在 created() 等事件里 dispatch 一个带模型 ID 和关键字段的 job,然后在 job handle 中重新查询最新数据
  • 如果任务必须等事务提交后再执行(比如发 webhook 通知外部系统),要用 DB::afterCommit() 包裹 dispatch,否则可能拿到脏数据或失败回滚

事情说清了就结束。Observer 看似简单,真正卡住人的永远是注册漏了、事件选错、或者在事务里误判了数据状态。

text=ZqhQzanResources