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

Symfony如何全局根据Content-Type动态返回对应格式的API响应?

解决Symfony全局根据请求Content-Type自动返回对应格式(含异常处理)

1. 配置请求格式自动识别

修改config/packages/framework.yaml,添加format_listener配置,让Symfony自动从请求的Content-Type或Accept头判断响应格式,且优先以Content-Type为准:

framework:
    # 其他原有配置...
    format_listener:
        enabled: true
        rules:
            - { path: '^/', prioritize_content_type: true, fallback_format: json, formats: { json: ['application/json'], xml: ['application/xml', 'text/xml'] } }

说明:

  • prioritize_content_type: true:优先依据请求的Content-Type确定响应格式,而非Accept头
  • fallback_format: json:当无法识别请求格式时,默认返回JSON格式
  • formats:定义支持的格式与对应MIME类型的映射关系

2. 自定义异常格式处理器

创建异常订阅者,确保异常响应也遵循请求指定的格式:

在src/EventSubscriber/ExceptionFormatSubscriber.php中编写以下代码:

<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\SerializerInterface;

class ExceptionFormatSubscriber implements EventSubscriberInterface
{
    private $serializer;

    public function __construct(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ExceptionEvent::class => 'onKernelException',
        ];
    }

    public function onKernelException(ExceptionEvent $event): void
    {
        $request = $event->getRequest();
        $exception = $event->getThrowable();
        $format = $request->getRequestFormat();

        // 构建统一的异常响应数据结构
        $errorData = [
            'status' => method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : Response::HTTP_INTERNAL_SERVER_ERROR,
            'message' => $exception->getMessage(),
        ];

        // 根据请求格式生成对应响应
        if ($format === 'json') {
            $response = new JsonResponse($errorData, $errorData['status']);
        } elseif ($format === 'xml') {
            $xmlContent = $this->serializer->serialize($errorData, 'xml');
            $response = new Response($xmlContent, $errorData['status'], ['Content-Type' => 'application/xml']);
        } else {
            // 无法识别格式时 fallback 到JSON
            $response = new JsonResponse($errorData, $errorData['status']);
        }

        $event->setResponse($response);
    }
}

3. 路由配置保持简洁

无需在routes.yaml中手动添加_format参数,保持常规路由配置即可,例如:

api:
    resource: '../src/Controller/'
    type: annotation
    prefix: /api

完成以上配置后,无论请求的Content-Type是application/json还是application/xml,接口的正常响应和异常响应都会自动匹配对应格式返回,无需手动指定格式参数。

内容的提问来源于stack exchange,提问作者Akif Tezcan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:25:35