symfony中创建中间件需通过kernel.request和kernel.response事件监听器实现,注册时须添加kernel.event_subscriber标签,优先级设为10并检查ismainrequest以避免子请求重复执行。

在 Symfony 中创建中间件需通过 HTTP 内核层的事件监听器实现,因为 Symfony 本身不提供原生“中间件”概念,而是用 kernel.request 和 kernel.response 事件配合监听器模拟中间件行为。直接写控制器逻辑会污染业务代码,而监听器能统一拦截请求、修改响应、记录日志或拒绝非法访问,且无需修改路由或控制器。
注册内核事件监听器
在 src/EventListener/ 下新建 RequestLoggerListener.php,实现 EventSubscriberInterface 接口。
运行 php bin/console make:subscriber RequestLogger 命令快速生成骨架类,它会自动在 config/services.yaml 中添加服务标签 kernel.event_subscriber。
若手动注册,必须确保服务定义中包含 tags: [{ name: 'kernel.event_subscriber' }],否则监听器不会被内核识别。
监听 kernel.request 事件做请求预处理
方法一:在 getSubscribedEvents() 中返回 KernelEvents::REQUEST => ['onKernelRequest', 10]。
方法二:使用字符串数组语法 ['kernel.request' => ['onKernelRequest', 10]],优先级数值越小越早执行,10 是常见中间件级优先级;低于 0 的优先级(如 -10)会被用于安全防火墙等核心逻辑,普通中间件别乱设。
在 onKernelRequest() 方法中,先检查 $event->isMainRequest(),避免对子请求(如嵌入的控制器片段)重复执行;不加这个判断会导致模板中 render(controller(...)) 调用时日志被打印两次。
【$event->getRequest() 返回的是 Request 对象,可直接调用 ->getHeaders()、->getClientIp() 等方法】
修改响应内容并终止后续流程
第一步:监听 kernel.response 事件,在 getSubscribedEvents() 中添加 KernelEvents::RESPONSE => 'onKernelResponse'。
第二步:在 onKernelResponse() 方法中获取响应对象:$response = $event->getResponse()。
第三步:调用 $response->setContent(str_replace('Symfony', 'PHP Framework', $response->getContent())) 替换 HTML 响应体中的关键词——注意这仅对文本型响应有效,JSON 或二进制响应会损坏。
第四步:若需提前终止响应(例如权限校验失败),直接调用 $event->setResponse(new Response('Access Denied', 403)) 并 return,后续监听器和控制器将不再执行。
基于请求路径条件启用监听器
在 onKernelRequest() 开头加入路径判断:if (!str_starts_with($request->getPathInfo(), '/api')) { return; }。
这一步让监听器只作用于 API 路由,避免干扰后台管理页或静态资源请求。
不要用 $request->getBaseUrl() 拼接判断,它依赖服务器配置,容易在 CLI 或反向代理环境下出错。











