不需要。Eloquent Observer 是普通 PHP 类,仅需方法名匹配生命周期事件(如 created、updating)即可被反射调用,无需继承 ModelObserver 或实现接口。

Observer类必须继承ModelObserver吗?
不需要。Eloquent Observer 是一个普通 PHP 类,只要方法名匹配模型生命周期事件(如 created、updating、deleted),就能被自动调用。Laravel 不强制继承任何基类,也不要求实现接口——它靠方法名反射触发。
常见错误是手动在模型里写 $dispatchesEvents 却忘了注册 Observer,或把方法名拼错成 create(少了个 d),导致完全不触发。
-
created:插入数据库后触发(已分配主键) -
saving/updating:在保存前触发,可修改属性或return false中断保存 -
deleting:软删除和硬删除都会触发;deleted则只在删除成功后触发 - 软删除模型要监听
restoring和restored,不是retrieving
如何注册Observer并确保生效?
最可靠的方式是通过 EventServiceProvider 的 $listen 或 boot() 方法全局注册,而不是在模型构造函数或静态 boot() 里调用 observe() —— 后者容易因模型加载顺序问题漏注册。
推荐做法是在 app/Providers/EventServiceProvider.php 的 boot() 中写:
立即学习“PHP免费学习笔记(深入)”;
use App\Models\Post;
use App\Observers\PostObserver;
public function boot()
{
Post::observe(PostObserver::class);
}
注意:PostObserver 类路径必须正确,且类文件存在;如果用 IDE 自动导入,可能误引入了同名但非 Observer 的类。
- 多个模型共用一个 Observer?可以,只要方法名能区分,比如
PostObserver里同时定义created和userCreated,再配合if ($model instanceof User)分支处理 - 临时禁用 Observer?可用
Post::withoutEvents(fn () => Post::create([...])) - 测试时忘记清空 Observer 缓存?运行
php artisan config:clear或重启队列 worker
saving 和 creating 哪个更适合做数据清洗?
saving 更合适。它在所有保存操作(create、update、save)前统一触发,适合做字段标准化(如 trim、转小写、补默认值);而 creating 只在首次插入时触发,对后续更新无效。
典型场景:用户注册时邮箱自动转小写,但编辑资料时也应保持一致。
public function saving(Post $post)
{
$post->title = trim($post->title);
$post->slug = Str::slug($post->title); // 避免重复生成
}
- 不要在
saving里调用$post->save(),会引发无限递归 - 若需校验失败中断保存,直接
return false,不要抛异常(否则事务行为不可控) - 涉及关联数据变更(如同步 tags 表),建议改用事件+队列,避免 Observer 里写重逻辑
软删除模型的 deleted 为什么没执行?
因为默认情况下,delete() 对软删除模型只执行标记(updated_at + deleted_at),不真正删记录,所以触发的是 trashed(Laravel 9+)或 deleted(旧版),但前提是 Observer 已注册且模型启用了 SoftDeletes trait。
检查点:
- 模型是否 use
Illuminate\Database\Eloquent\SoftDeletes? - 数据库字段
deleted_at是否为 nullable timestamp? - Laravel 版本是否 ≥9?9+ 把
deleted拆成了trashed(软删)和forceDeleted(硬删) - 是否误用了
destroy()而不是delete()?destroy()是静态方法,不触发实例 Observer
硬删必须显式调用 forceDelete(),对应监听 forceDeleted。



















