Как я могу получить доступ к контейнеру в прослушивателе перед ядром в Symfony2?

Я пытаюсь реализовать прослушиватель перед ядром (см. ссылку), где я просто установить некоторые значения параметров (которые я должен получить динамически и не могу статически объявить в моем файле parameters.yml).

Это мой класс слушателя:

class AcmeListener
{
    public function onKernelController(FilterControllerEvent $event)
    {
        $event->getController()->getContainer()->setParameter('foo', 'bar');
    }
}

И в моем config.yml:

services:
    kernel.listener.acme_listener:
        class: Acme\AcmeBundle\EventListener\AcmeListener
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Но я получаю

FatalErrorException: Ошибка: вызов функции-члена getContainer() для необъекта

Как я могу получить доступ к контейнеру, если не через getContainer() из $event->getController()?


person Gottlieb Notschnabel    schedule 17.04.2014    source источник


Ответы (1)


Просто добавьте контейнер в качестве аргумента в определение службы.

services:
    kernel.listener.acme_listener:
        class: Acme\AcmeBundle\EventListener\AcmeListener
        arguments:
            - @service_container
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Затем добавьте конструктор в свой класс AcmeListener, чтобы вы могли получить к нему доступ.

use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

class AcmeListener
{
    /**
     * @var Container
     */
    private $container;

    /**
     * Constructor
     *
     * @param Container $container
     */
    public function __construct(Container $container)
    {
            $this->container = $container;
    }

    public function onKernelController(FilterControllerEvent $event)
    {
            $this->container->...
    }
}
person Mark    schedule 17.04.2014
comment
Выглядит многообещающе, но я получаю LogicException: Impossible to call set() on a frozen ParameterBag. - person Gottlieb Notschnabel; 17.04.2014
comment
Должен ли я переключиться на onKernelRequest вместо onKernelController? - person Gottlieb Notschnabel; 17.04.2014
comment
Возможно. Оглядываясь назад на то время, когда я это делал, я использовал onKernelRequest. Это все еще соответствует вашим потребностям? - person Mark; 17.04.2014
comment
Теперь я вижу вашу проблему. Документы предлагают некоторую информацию по этому поводу: вы можете установить параметр только до того, как контейнер будет скомпилирован. Дополнительные сведения о компиляции контейнера см. в разделе Компиляция контейнера. symfony.com/doc/current/components/dependency_injection/ - person Mark; 17.04.2014
comment
Вы должны принять ответ @Mark, поскольку он показывает, как получить доступ к контейнеру. Хотя лично я бы реализовал интерфейс ContainerAware вместо внедрения контейнера в конструктор. Но его решение работает. Обновление замороженного пакета параметров - это совсем другой вопрос и в принципе не возможно. Вам нужно делать такие вещи, используя семантическую конфигурацию. - person Cerad; 17.04.2014
comment
@Cerad да, ты прав. Ответ объясняет, как получить доступ к контейнеру, поэтому я принимаю его. Спасибо вам, Марк, за помощь :-) Задам еще вопрос по поводу FrozenParameter. - person Gottlieb Notschnabel; 17.04.2014
comment
Кстати: использование onKernelRequest по-прежнему вызывает ту же ошибку. - person Gottlieb Notschnabel; 18.04.2014