中间件用于干预请求响应流,事件监听用于响应业务动作;中间件在kernel::handle()中修改request/response或控制流程,事件监听在业务发生后异步执行如发邮件、记日志。

中间件和事件监听不是“选一个”,而是“在哪个环节用哪个”——关键看你要干预的是请求响应流本身,还是对某个业务动作做反应。
需要修改 Request/Response 或控制执行流程?用中间件
比如统一加 CORS 头、拦截未登录请求跳转、解析 JWT 放入 $request->attributes、重写 URL 路径、记录请求耗时并写入 Response Header。这些操作必须发生在 Kernel::handle() 主干中,且能决定是否继续向下传递。
-
__invoke(Request $request, RequestHandlerInterface $next): Response是唯一入口,你必须返回Response或调用$next() - 中间件天然共享同一生命周期内的服务实例(如
Session、Request),但不能访问EventDispatcher之外的事件系统 - 别在中间件里调
Event::trigger()做核心逻辑——它会脱离当前请求上下文,且无法被事务包裹
想在用户注册后发邮件、订单创建后更新库存、登录后记日志?用事件监听
这类行为不参与请求链路,也不该阻断主流程;它们是“发生了某事之后顺便做的事”。TP6 的 event() 或 Event::trigger() 正是为此设计。
- 监听器的
handle()方法参数类型由你触发方式决定:用event(new UserRegistered($user))→ 参数是UserRegistered实例;用event('user_registered', $data)→ 参数就是原始$data - 配置必须同时满足三件事:
config/app.php中'event' => true(TP6.0.3+ 已强制开启)、config/event.php的listen键正确绑定、监听器类路径可自动加载 - CLI 环境下容易静默失效——因为
app/common.php可能没加载,或命令行入口绕过了 event 配置
TP5 和 TP6 的事件机制根本不是一回事
TP5 没有 event() 函数,也没有 think\facade\Event,它用的是 \think\Hook 静态类,所有注册都靠 \think\Hook::add() 手动完成,且只认字符串标识,不支持事件类、类型提示、自动依赖注入。
- TP5 中写
event('user_login')会直接报Fatal error: Call to undefined function event() - TP5 的钩子注册必须在应用初始化早期(如
app/common.php),控制器里重复调用add()会导致监听器执行多次 - TP6 的事件系统可关闭(旧版),但 TP6.0.3+ 已移除开关,
config/app.php中的'event'配置项已无效
最常被忽略的一点:中间件拿不到 Doctrine 或 Eloquent 的 postFlush 类事件,事件监听器也改不了 Response Header——边界就在那里,硬跨过去只会让调试变成猜谜。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











