Возврат JSON на основе "Accept: application/json" из контроллера Symfony2 без изменения каждого действия контроллера

Я работаю над приложением, которое хочу предложить как 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;
}

Это отлично работает. Если вы отправляете HTTP-заголовок Accept, это точно application/json, вы получите обратно JSON. В противном случае вы получите обычный вид hTML.

Это прекрасно работает, но у меня есть десятки действий. Я бы предпочел не повторяться. Я работаю над рефакторингом этого кода во что-то более общее... но мне также интересно, решена ли эта проблема уже существующим пакетом Symfony2. Может быть, что-то с аннотациями? Или настройки конфига? Я пока не смог ничего найти. Но я настолько новичок в Symfony, что могу легко что-то упустить.

2 ответа

В качестве общей идеи, если вы хотите избежать использования сторонних пакетов, вы можете подписаться на событие kernel.response и поиграть с 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 ...
    }
}

Пакет, который вы ищете, это FOSRestBundle.

Вы можете использовать JSON на основе заголовка Accept или добавления _format к вашим маршрутам... настраиваемый.

Хорошо работает с JMSSerializerBundle.

Другие вопросы по тегам