TP8中event()函数已失效,必须改用Event::trigger()触发事件;事件需在app/event.php中同时配置bind和listen;模型事件须手动监听且仅支持单参数handle()方法。

event() 函数已失效,必须改用 Event::trigger()
TP8 中 event() 函数不再触发任何监听器,它只是个空壳或兼容占位符。所有事件触发必须走 Event::trigger() 静态方法,否则监听器完全不会执行——而且不报错、不提示、无声无息失败。
常见错误现象:代码里还写着 event('UserLogin', $data),本地开发“好像能跑”,上线后监听器彻底失联。
- ✅ 正确写法:
Event::trigger('UserLogin', ['uid' => 123, 'ip' => $request->ip()]) - ❌ 错误写法:
event('UserLogin', [...])、event()->trigger(...)、\think\Event::trigger(...)(类路径已变更) - ⚠️ 注意:事件名可以是字符串,也可以是事件类实例(如
new UserLogin($data)),但后者需确保该类被 PSR-4 自动加载且命名空间正确
app/event.php 中 bind 和 listen 必须同时配置
TP8 的事件系统依赖显式绑定(bind)与监听注册(listen)双动作,缺一不可。只写 listen 不写 bind,或者反过来,监听器都不会被调用。
使用场景:你想监听一个叫 UserLogin 的事件,对应监听器类是 app\listener\UserLogin。
立即学习“PHP免费学习笔记(深入)”;
- 在
app/event.php的'bind'数组中加:'UserLogin' => 'app\event\UserLogin'(若用事件类)或直接'UserLogin' => 'UserLogin'(若用字符串名) - 在同文件的
'listen'数组中加:'UserLogin' => ['app\listener\UserLogin'] - 别写成
'UserLogin' => ['app\listener\UserLogin::handle']—— TP8 不支持方法级注册,只认类名
模型事件监听方式完全不同,没有自动绑定
TP6 可能在模型里写 $dispatchesEvents = ['created' => UserCreated::class],TP8 完全不识别这个属性。模型事件(如 model.before_insert)必须手动监听,且只能在初始化阶段注册。
性能与兼容性影响:延迟注册(比如在控制器里调用 event()->listen())无效;批量操作(User::where()->update())不走模型实例,因此不触发任何模型事件。
- ✅ 推荐注册位置:
app/common/Event.php的bind()方法,或app/bootstrap.php - ✅ 正确监听写法:
event()->listen('model.before_write', [UserObserver::class, 'onBeforeWrite']) - ⚠️ 回调接收唯一参数:
$model实例,不是原始数据数组;before_*类可调用$model->data($new)并返回false阻断流程,但会跳过验证和时间戳填充
监听器 handle() 方法只允许一个参数
TP8 强制约定监听器的 handle() 方法只能接收一个参数,就是 Event::trigger() 的第二个参数(无论它是数组、对象还是 null)。试图拆成多个形参会导致 TypeError 或静默忽略。
容易踩的坑:从 TP6 迁移时保留了旧写法,比如 public function handle($uid, $ip),TP8 会直接跳过该监听器,不报错也不执行。
- ✅ 正确签名:
public function handle($payload): void - ✅ 若需解构,手动处理:
$uid = $payload['uid'] ?? null; $ip = $payload['ip'] ?? ''; - ⚠️ 注意:
$payload是原样透传,不做类型转换或结构校验,需监听器自行判断



















