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
相关产品推荐
相关产品推荐

