Symfony 4中如何在ExceptionListener内访问Logger服务
在Symfony的ExceptionListener中使用Logger服务的正确姿势
嘿,在Symfony里用Logger服务可不能自己随便new对象哦~正确的姿势是通过**依赖注入(Dependency Injection)**来获取框架已经配置好的Logger实例,我给你一步步讲清楚怎么弄:
1. 通过构造函数注入LoggerInterface
Symfony的日志系统实现了PSR-3标准的LoggerInterface,我们只需要在监听器的构造函数里注入这个接口就行,不用关心具体的实现类。
先看修改后的完整代码:
use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; class ExceptionListener { // 用私有属性保存Logger实例 private $logger; // 构造函数注入Logger服务 public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); // 这里可以根据需求选择日志级别:error/warning/info等 $this->logger->error( '捕获到异常', [ '异常类' => get_class($exception), '错误消息' => $exception->getMessage(), 'HTTP状态码' => $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500, '堆栈跟踪' => $exception->getTraceAsString() ] ); if ($exception instanceof HttpExceptionInterface) { $response = new JsonResponse( ['error' => $exception->getMessage()], $exception->getStatusCode() ); } else { // 处理非HTTP类型的异常,返回通用500错误 $response = new JsonResponse( ['error' => '服务器内部错误'], 500 ); } $event->setResponse($response); } }
2. 确保监听器被正确注册为服务
接下来要让Symfony的服务容器知道这个监听器,分两种情况:
情况一:开启了Autowire(Symfony 3.4+默认开启)
只需要在config/services.yaml里给监听器打上事件监听的标签就行,容器会自动帮你注入Logger:
# config/services.yaml services: App\EventListener\ExceptionListener: tags: - { name: kernel.event_listener, event: kernel.exception }
情况二:没开启Autowire
需要手动指定构造函数的参数,把框架默认的logger服务传进去:
# config/services.yaml services: App\EventListener\ExceptionListener: arguments: $logger: '@logger' tags: - { name: kernel.event_listener, event: kernel.exception }
3. 为什么不直接创建Logger对象?
- Symfony默认的Logger已经配置好了日志路径、级别过滤、格式化规则等,自己new的话完全用不上这些配置;
- 依赖抽象接口(
LoggerInterface)而不是具体实现,后续如果要替换日志组件(比如换成Monolog的其他配置),代码完全不用改; - 方便单元测试,你可以轻松Mock一个
LoggerInterface来验证日志是否正确输出,不用依赖真实的日志文件。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

