2016-05-19 2 views
1

В моем проекте Symfony я столкнулся с причудливой проблемой: kernel.requestevent listeners стрельбы несколько раз, когда используются embedded Twig controllers.Встраиваемые контроллеры Twig вызывают многократные события ядра.request

В моем пользовательском прослушивателе событий у меня есть прослушиватель событий, который отправляет ответ перенаправления, если существует определенное условие (в этом случае истекший пароль). Для того, чтобы предотвратить петлю перенаправлять я проверил, если мы уже были на странице:

if ($event->getRequest()->get('_route') != 'user_change_password') { 
    $response = new RedirectResponse($this->router->generate('user_change_password')); 
    $event->setResponse($response); 
} 

Но это не остановило петли перенаправления. Пока я не добавил регистрацию, я понятия не имел, что встроенный контроллер будет запускать событие kernel.request (это очевидно в ретроспективе, поскольку эти встроенные контроллеры работают, отправляя «подпроцесс»). У меня есть один встроенный контроллер в шаблоне базовой ветви, который проверяет наличие предупреждающих сообщений и отображает их.

Учитывая вышеизложенное, как я могу

  1. иметь возможность вставить динамическое содержимое в базовый шаблон (все другие шаблоны расширения), и
  2. не kernel.request слушателей событий срабатывала несколько раз.

Несмотря на то, что Symfony предлагает вставить этот динамический контент в базовые шаблоны с использованием встроенных контроллеров, считается ли это плохой практикой?

Было бы лучше создать Twig extension, чтобы решить эту проблему? Из того, что я видел, расширения Twig обычно используются только для простых вещей, таких как пример price в кулинарной книге, хотя я не понимаю, почему это не сработает для более сложных, связанных с базой данных вещей. Я просто не знаю, как это сделать.

Примеры приветствуются.


Возможные связанные ?: Symfony Controller executed multiple Time

+0

kernel.request уволен для каждого запроса, в том числе подзапросы, такие как {{render (controller ('...'))}} –

+0

Правильно, вот что я сказал. Я пытался найти решение проблемы, описанной выше, которую любезно предоставил xabbuh. – user128216

ответ

4

Вы можете сделать переадресацию только, если слушатель события выполняется для мастер-запроса:

use Symfony\Component\HttpKernel\HttpKernelInterface; 

// ... 

if ($event->isMasterRequest() && $event->getRequest()->get('_route') != 'user_change_password') { 
    $response = new RedirectResponse($this->router->generate('user_change_password')); 
    $event->setResponse($response); 
} 

Если вы все еще связаны с Symfony 2.3, вы может использовать метод getRequestType() сравнить его возвращаемое значение с константой MASTER_REQUEST от HttpKernelInterface (вот что isMasterRequest() делает внутренне):

use Symfony\Component\HttpKernel\HttpKernelInterface; 

// ... 

if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType() && $event->getRequest()->get('_route') != 'user_change_password') { 
    $response = new RedirectResponse($this->router->generate('user_change_password')); 
    $event->setResponse($response); 
} 
+0

Бинго! Это то, что мне нравится: быстро и просто. Спасибо! Одна вещь: метод, по-видимому, был переименован в '$ event-> getRequestType()' в Symfony3. Кроме того, полное пространство имен (для оператора 'use') - это' Symfony \ Component \ HttpKernel \ HttpKernelInterface'. – user128216

+0

Я заглядывал в источник, и я нашел более простой способ. Существует метод событий, называемый 'isMasterRequest()', который выполняет точное сопоставление requestType в ответе. Не уверен, когда это было добавлено в Symfony, но это предпочтительное решение. – user128216

+0

Вы правы. Метод был введен в Symfony 2.4. Я снова обновил свой ответ, чтобы кто-то споткнул об этом в будущем. – xabbuh