基于“Accept:application / json”从Symfony2控制器返回JSON,而不修改每个控制器操作

时间:2013-05-23 01:14:56

标签: json http symfony http-headers

我正在开发一个我想提供JSON和HTML响应的应用。这是一个示例动作方法:

/**
 * Lists all Boards entities.
 *
 * @Route("/", name="boards")
 * @Method("GET")
 * @Template()
 */
public function indexAction()
{
    $em = $this->getDoctrine()->getManager();

    $entities = $em->getRepository('ScrumBoardServiceBundle:Boards')->findAll();

    $acceptHeader = strtolower($this->getRequest()->headers->get('Accept'));
    if ($acceptHeader === 'application/json') {
        $serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new
                JsonEncoder()));
        $response = $serializer->serialize(array('success' => true, 'data' => array(
                'entity' => $entities,
        )), 'json');
        $result = new Response($response, 200, array('Content-Type' => 'application/json'));
    } else {
        $result = array(
            'entities' => $entities,
        );
    }

    return $result;
}

这很好用。如果您发送完全 application/json的HTTP Accept标头,您将获得JSON。否则,您将获得通常的hTML视图。

这很好,但我有很多动作。我宁愿不重复自己。我正在努力将这些代码重构为更通用的东西...但我也想知道现有的Symfony2捆绑包是否已经解决了这个问题。也许有注释的东西?还是配置设置?到目前为止我还没找到任何东西。但我对Symfony这么新,我很容易错过一些东西。

2 个答案:

答案 0 :(得分:2)

作为一般概念,如果您想避免使用第三方捆绑包,您可以订阅kernel.response事件并在那里使用响应,只需在一个公共位置。

类似的东西:

// services.yml

services:
  my.kernel.listener:
    class: Acme\Bundle\AppBundle\EventListener\MyKernelListener
    tags:
      - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }

// MyKernelListener.php

class MyKernelListener
{
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $response = $event->getResponse();
        $request = $event->getRequest();
        // ... your logic ...
    }
}

答案 1 :(得分:1)

您正在寻找的捆绑包是FOSRestBundle

您可以根据Accept标头提供JSON服务,或者将_format添加到路由中......高度可配置。

JMSSerializerBundle合作很好。