Symfony 2.1 - Пользовательский Прослушиватель Аннотаций Json


Для проекта Symfony 2.1 я пытаюсь создать новую аннотацию @Json(), которая зарегистрирует прослушиватель, который автоматически создаст объект JsonResponse при возврате массива. У меня это работает, но по какой-то причине слушатель всегда вызывается, даже для методов, у которых нет аннотации @Json. Я предполагаю, что мой подход работает, так как дополнительный пакет Sensio делает это с аннотацией @Template.

Вот мой код аннотации.

<?php

namespace Company\Bundle\Annotations;

/**
 * @Annotation
 */
class Json extends \Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationAnnotation
{
    public function getAliasName()
    {
        return 'json';
    }
}

Здесь это мой код слушателя.

<?php

namespace Company\Bundle\Listener\Response\Json;

class JsonListener
{
    //..

    public function onKernelView(GetResponseForControllerResultEvent $event)
    {
        $request = $event->getRequest();
        $data = $event->getControllerResult();

        if(is_array($data) || is_object($data)) {
            if ($request->attributes->get('_json')) {
                $event->setResponse(new JsonResponse($data));
            }
        }
    }
}

Это мое определение yaml для слушателя.

json.listener:
            class:      Company\Bundle\Listener\Response\Json
            arguments:  [@service_container]
            tags:
                - { name: kernel.event_listener, event: kernel.view, method: onKernelView }

Я, очевидно, что-то здесь упускаю, потому что он зарегистрирован как прослушиватель ядра.просмотр. Как мне изменить это, чтобы оно вызывалось только тогда, когда в действии контроллера присутствует аннотация @Json()?

Author: Jarrod Nettles, 2013-02-21

1 answers

Не претендуйте на окончательный ответ.

Я не совсем понимаю, почему вы расширяете ConfigurationAnnotation: его конструктор принимает array, но вам не нужна никакая конфигурация для вашей аннотации. Вместо этого реализуйте ConfigurationInterface:

namespace Company\Bundle\Annotations;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;

/**
 * @Annotation
 */
class Json implements ConfigurationInterface
{
    public function getAliasName()
    {
        return 'json';
    }

    public function allowArray()
    {
        return false;
    }
}

Сенсио ControllerListener из SensionFrameworkExtraBundle прочитает вашу аннотацию (объединение класса с аннотациями методов) и выполнит эту проверку:

if ($configuration instanceof ConfigurationInterface) {
    if ($configuration->allowArray()) {
        $configurations['_'.$configuration->getAliasName()][] = $configuration;
    } else {
        $configurations['_'.$configuration->getAliasName()] = $configuration;
    }
}

Установка атрибута запроса с префиксом _. Вы правильно проверяя _json, так что это должно сработать. Попробуйте сбросить $request->attributes в прослушивателе событий вашего представления. Убедитесь, что ваш сервис json.listener также правильно загружен (сбросьте их с php app/console container:debug >> container.txt).

Если это не сработает, попробуйте добавить некоторые инструкции отладки и печати здесь (найдите ControllerListener.php в папке поставщика):

var_dump(array_keys($configurations)); // Should contain _json

Не забудьте сделать его копию перед редактированием, иначе Composer выдаст ошибку при обновлении зависимостей.

 1
Author: gremo, 2013-02-21 11:47:38