该用模型观察者而非事件监听器的场景是仅对单一模型做轻量级副作用处理,如自动填充slug、同步计数、记录日志;涉及多模型、队列、跨服务调用时应选原生事件+监听器。

什么时候该用模型观察者而不是事件监听器
模型观察者是 Laravel 提供的语法糖,本质是把 creating、saving、deleting 等模型事件统一收口到一个类里。它适合「只对单一模型做轻量级副作用处理」的场景,比如自动填充 slug、同步更新关联计数、记录操作日志字段。如果逻辑涉及多个模型、需要队列延迟、或要跨服务调用(如发短信、调外部 API),直接用原生事件 + 监听器更清晰可控。
如何注册模型观察者并避免不生效
常见失效原因不是写法错,而是注册时机或位置不对。必须确保观察者在模型被首次加载前完成绑定,否则事件不会触发。推荐在 AppServiceProvider::boot() 中注册:
use App\Models\Post;
use App\Observers\PostObserver;
public function boot()
{
Post::observe(PostObserver::class);
}
注意:PostObserver 类名必须与模型名匹配(如 Post → PostObserver),否则 IDE 可能提示找不到类;观察者方法名必须严格为 created、updated、deleted 等,不能写成 onCreated 或 afterCreate;Laravel 9+ 默认启用模型事件,但若项目中手动关闭过 Model::shouldBeStrict() 或修改过事件调度器,需检查 config/app.php 中是否误删了 Illuminate\Database\DatabaseServiceProvider。
observer 方法里不能直接 throw Exception
在 saving 或 updating 中抛出异常会导致事务中断,但 Laravel 不会自动回滚——除非你显式开启事务。更稳妥的做法是返回 false 终止保存流程:
public function saving(Post $post)
{
if (empty($post->title)) {
return false; // 拦截保存,Eloquent 会停止后续操作
}
}
而 saved、updated 这类“已落地”后的方法,再抛异常就晚了,数据库已写入。此时若需补救,只能靠事务包裹整个业务逻辑,不能依赖 observer 单点控制。
软删除模型的 observer 方法名容易混淆
软删除触发的是 deleting 和 deleted,不是 forceDeleting。只有调用 forceDelete() 才会触发后者。对应地,恢复软删除走的是 restoring 和 restored,不是 updating。这些方法名必须一字不差:
-
deleting:软删前(模型还在内存,可修改) -
deleted:软删后(deleted_at已写入) -
forceDeleting:硬删前(绕过软删,慎用) -
restoring:restore() 调用前
少个 s 或大小写错误,方法就不会被调用,且无任何报错提示。










