Symfony错误处理无法返回JSON响应?求排查解决方法
Symfony REST API 异常无法返回JSON响应的排查与解决
问题概述
使用Symfony开发REST API时,遇到404等异常场景无法返回JSON字符串,已尝试自定义ExceptionListener并在services.yaml中注册,但仍返回默认的HTML错误模板。
现有代码
ExceptionListener实现
<?php namespace App\EventListener; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; class ExceptionListener { public function onKernelException(ExceptionEvent $event) { $exception = $event->getThrowable(); $message = sprintf( 'My Error says: %s with code: %s', $exception->getMessage(), $exception->getCode() ); echo "error happened"; $response = new Response(); $response->setContent($message); if ($exception instanceof HttpExceptionInterface) { $response->setStatusCode($exception->getStatusCode()); $response->headers->replace($exception->getHeaders()); } else { $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR); } $event->setResponse(new JsonResponse($this->translator->trans('not_found'))); return new JsonResponse($this->translator->trans('not_found')); } }
services.yaml配置
parameters: services: App\EventListener\ExceptionListener: tags: - { name: kernel.event_listener, event: kernel.exception }
问题排查与修复
你的代码存在几个关键问题导致JSON响应不生效:
未注入Translator服务
代码中直接使用$this->translator,但类内未定义该属性,也未通过构造函数注入服务,会抛出致命错误中断监听器逻辑。
修复:添加构造函数注入TranslatorInterface:use Symfony\Contracts\Translation\TranslatorInterface; class ExceptionListener { private $translator; public function __construct(TranslatorInterface $translator) { $this->translator = $translator; } // 原有方法逻辑 }监听器优先级不足
Symfony自带的异常监听器优先级可能高于你的自定义监听器,先处理异常并返回HTML响应。需要给自定义监听器设置更高优先级:
修改services.yaml标签配置:App\EventListener\ExceptionListener: tags: - { name: kernel.event_listener, event: kernel.exception, priority: 100 }优先级数值越大,执行顺序越靠前,确保你的监听器先处理异常。
无效的return语句
onKernelException是事件监听器方法,不需要返回响应,仅需通过$event->setResponse()设置响应即可。代码中的return new JsonResponse(...)完全无效,直接删除。echo语句破坏响应
echo "error happened";会向输出缓冲区写入内容,破坏JSON响应的完整性,必须删除。添加API请求判断(可选)
如果应用同时包含网页和API,建议只对API请求返回JSON响应,可通过请求头或路由前缀判断:$request = $event->getRequest(); // 判断请求是否期望JSON响应 if (!$request->headers->has('Accept') || !str_contains($request->headers->get('Accept'), 'application/json')) { return; // 非API请求,交给默认逻辑处理 }正确构建JSON响应
原代码仅返回固定翻译文本,应根据异常类型返回对应信息和状态码:$statusCode = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : Response::HTTP_INTERNAL_SERVER_ERROR; $errorMessage = $exception->getMessage() ?: $this->translator->trans('not_found'); $jsonResponse = new JsonResponse([ 'error' => $errorMessage, 'code' => $statusCode ], $statusCode); if ($exception instanceof HttpExceptionInterface) { $jsonResponse->headers->replace($exception->getHeaders()); } $event->setResponse($jsonResponse);
内容的提问来源于stack exchange,提问作者Fabian Andiel
相关产品推荐
相关产品推荐

