tp6已彻底移除hook机制,无法使用hook::listen()等方法;应改用think-event(psr-14)事件系统,通过event::trigger()触发自定义事件,并在event.php中绑定监听器。

ThinkPHP 6.0 里没有 Hook::listen(),直接调就会报 Fatal error: Class 'think\facade\Hook' not found 或者 Call to undefined method think\facade\Hook::listen() —— 因为钩子机制在 TP6 中已被完全移除,不是“不推荐”,是物理删除。
TP6 还能用 Hook::add() / Hook::listen() 吗
不能。所有 think\facade\Hook 相关调用都会失败。TP6 的源码里已删掉 think\Hook 类和全部 facade 绑定。即使你手动复制 TP5 的 Hook.php 到项目里,也会因依赖 App 实例、$this->hook->import() 等未注册容器服务而静默失效 —— 不报错,但行为类根本不会执行。
常见误操作:
- 在控制器里写
Hook::listen('app_init'),以为能触发初始化行为 → 实际什么也不发生 - 把 TP5 的
tags.php直接挪到 TP6 项目里 → 配置被忽略,app_init等标签位不再被框架读取 - 试图用
composer require topthink/think-hook补丁 → 该包非官方维护,与 TP6 容器、事件总线不兼容,大概率导致Class not found或监听器不调用
TP6 替代方案:用 think-event(PSR-14)注册监听器
TP6 默认使用 topthink/think-event(基于 PSR-14),核心是 think\Event 门面和 think\event\Event 类。监听器必须是可调用对象,参数完全由你定义,不再强制只传一个 $params。
实操步骤:
- 监听器类放在
app/listener/下,例如app/listener/AppInitLogger.php,无需继承基类,方法名任意(如handle、onAppInit都行) - 在
app/event.php中绑定事件名与监听器:return [ 'bind' => [ 'AppInit' => ['app\listener\AppInitLogger'], ], ]; - 触发事件用
think\Event::trigger('AppInit', [$request]),参数数组按需传,支持多个参数 - 若想在框架启动时自动监听(类似旧版
app_init),需在服务提供者中注册,例如在app/provider.php里加:use think\Event; use app\listener\AppInitLogger; return [ AppInitLogger::class, // 并在 register() 方法中: // Event::listen('AppInit', [AppInitLogger::class, 'handle']); ];
为什么自己写的 Hook::listen('xxx') 在 TP6 里不报错也不执行
因为 PHP 找不到 Hook 类,会直接抛出 Fatal error —— 除非你提前 class_alias() 或手动 require 了某个假 Hook 类,才可能“静默失败”。真正容易被忽略的点是:
- TP6 的生命周期钩子(如应用初始化、请求开始)已由中间件和事件系统接管,
app_init这种标签位本身就不复存在,不存在“预留插槽” - 框架内部不再调用任何
Hook::listen(),所以你在任意位置写它,都只是孤立的函数调用,无上下文、无注册表、无执行环境 - 调试时用
trace()或日志打点看不到效果,不是代码问题,是机制已下线
最后提醒:TP6 的事件名是自由字符串,不是预定义常量;监听器可以是闭包、静态方法、对象实例方法;但别再翻 TP5 文档抄 Hook::add() 示例——那套代码在 TP6 里从语法到语义都不成立。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











