You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:25:17