ThinkPHP 6.1+ 中 saved、deleting 等模型事件失效是因为框架彻底移除了魔术方法事件机制,必须通过观察者类(如 UserObserver)在模型 initialize() 中调用 observe() 显式注册,且方法名须为 created、updated 等小驼峰格式。

ThinkPHP 6.1+ 中 saved、deleting 等模型事件为何失效
因为 ThinkPHP 6.1 起彻底移除了模型类中直接定义 saved、updating 等魔术方法的事件机制,这些方法不再被自动调用。不是你写错了,是框架底层监听逻辑已重构——事件现在必须通过观察者(Observer)显式注册。
- 旧写法:
protected function saved()在模型里定义,6.1+ 完全不触发 - 新机制依赖
thinkmodelEvent和thinkeventListener,但官方推荐路径是观察者类 - 如果你还在用
model->event()手动绑定,要注意:事件名已统一为小驼峰(如after_save),而非旧版saved
如何正确创建并注册一个模型观察者类
观察者类本质是普通 PHP 类,只需实现对应方法,再通过 observe() 关联到模型。它比手动绑定事件更清晰,也支持批量监听多个模型。
- 新建类如
appobserveUserObserver.php,方法名必须是created、updated、deleted、restored等标准命名(注意不是afterCreate) - 在模型的
initialize()中调用self::observe('app\observe\UserObserver'),路径需完整且转义反斜杠 - 若使用容器注入,也可在
app/provider.php中全局注册:Model::observe(appobserveUserObserver::class) - 观察者方法接收参数为当前模型实例,例如
public function updated(User $model),可直接操作$model->id或调用$model->save()(但慎用,易引发循环)
常见踩坑:事件没触发?检查这四点
90% 的“观察者不生效”问题出在配置或命名细节上,和逻辑无关。
-
observe()调用位置错误:不能放在构造函数里,必须在initialize()静态方法中(该方法在模型首次加载时执行) - 类名或命名空间拼写错误,尤其是大小写——Linux 环境下
userobserver.php和UserObserver.php是两个文件 - 方法名写成
onUpdated或afterUpdate,实际只认updated(对应after_update事件) - 模型用了软删除但没实现
SoftDeletetrait,导致deleted方法不会被调用;应改用forceDeleted监听强制删除
替代方案:用 Event::listen() 手动监听是否更灵活
可以,但仅适合临时调试或跨模型通用逻辑。正式项目中观察者更利于维护。
立即学习“PHP免费学习笔记(深入)”;
- 监听点是事件名,如
thinkmodeleventAfterWrite(对应saved+updated),不是字符串"saved" - 需在
appcommonEvent.php或服务提供者中注册,否则每次请求都得重复绑定 - 性能略低:每个模型操作都会广播事件,而观察者只对注册的模型生效
- 示例:
Event::listen('thinkmodeleventAfterWrite', function ($model) { if ($model instanceof User) { /* 处理 */ } });
观察者不是语法糖,它是 TP6+ 的事件组织范式。漏掉 initialize() 里的 observe(),或者把方法名写成 Saved,就等于没写。


















