thinkphp的事件订阅和监听是两种不同机制:监听类通过handle()方法处理单一事件,需在event.php中配置bind和listen;订阅类通过on+驼峰命名响应多个事件,只需加入subscribe数组。

ThinkPHP 的事件订阅和监听不是同一种机制,用法、结构和配置逻辑完全不同。搞混就容易白写代码、触发不生效——尤其在 TP6/8 中,二者共存但职责分明。
监听类:一个类只处理一个事件
监听类的核心是 handle() 方法,它必须存在、名字不能改、签名要匹配触发方式。
- 生成命令:
php think make:listener UserLogin,会自动创建app/listener/UserLogin.php - 类里只写一个
public function handle($event),参数名随意,但类型取决于你如何触发:- 若
event('UserLogin', $data)→$event就是$data - 若
event(new UserLogin($user))→$event是UserLogin实例,可加类型提示:handle(UserLogin $event)
- 若
- 返回
false会中断后续同事件的其他监听器;返回其他值(包括null)不影响执行链 - 类无需继承任何基类,也不需要实现接口,只要方法名和调用方式对得上就行
订阅类:一个类响应多个事件
订阅类靠方法名约定事件响应关系,靠 on + 驼峰事件标识 匹配,比如事件标识是 UserLogin,就得写 onUserLogin()。
- 类本身不需特殊继承或实现,但必须放进
config/event.php的subscribe数组里 - 每个要监听的事件,都得单独写一个
onXXX()方法,不能共用入口 - 方法参数直接接收
Event::trigger()的第二个参数(或数组展开),不支持类型提示事件类(除非你自己 new 出来传进去) - 如果写了
subscribe()方法,框架会优先调用它,而忽略所有onXXX()方法——这是自定义注册逻辑的入口,不是必写项
event.php 配置必须“三件套”齐备
监听和订阅都要靠 event.php 激活,但各自依赖不同字段:
-
监听生效前提:必须同时配置
bind和listen-
bind['UserLogin'] = 'app\event\UserLogin'→ 把标识映射到事件类(可选,但推荐) -
listen['UserLogin'] = ['app\listener\SendEmail', 'app\listener\LogLogin']→ 把标识映射到监听器列表 - 键名大小写敏感,路径必须带双反斜杠或使用正斜杠,文件不能有 BOM 或多余空格
-
-
订阅生效前提:只需把类加进
subscribe数组,不需要bind或listen关联'subscribe' => ['app\subscribe\UserActionSubscribe']- 框架会自动扫描该类里的
onUserLogin、onUserLogout等方法并绑定
- 别把监听类误塞进
subscribe,也别把订阅类硬塞进listen—— 类型错位会导致静默失效
触发方式决定监听器能否收到数据
事件怎么发,监听器就怎么收,没有自动转换:
- 用字符串触发:
event('UserLogin', ['uid' => 123])→ 所有监听器handle()收到的是数组 - 用事件类触发:
event(new UserLogin($user))→ 所有监听器handle()收到的是对象(支持类型提示) - 订阅类的
onUserLogin()只能拿到触发时传的第二参数,不管你是字符串还是对象传的 - TP8 中
event()是助手函数,TP5 不支持,只能用hinkHook::trigger()替代
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











