Подзапросы в Symfony

Вероятно, вы знаете о том, что при вызове метода HttpKernel::handle() вторым параметром идёт аргумент типа запроса — $type:

public function handle(
    Request $request,
    $type = HttpKernelInterface::MASTER_REQUEST,
    $catch = true
) {
    ...
}

В интерфейсе HttpKernelInterface определены две константы, позволяющие определить тип запроса:

  1. HttpKernelInterface::MASTER_REQUEST — главный запрос (мастер)
  2. HttpKernelInterface::SUB_REQUEST — поздапрос

Для каждого запроса в вашем PHP-приложении первый запрос, который обрабатывается ядром, имеет тип мастер — HttpKernelInterface::MASTER_REQUEST. Это определено неявно, так как аргумент $type не указывается во фронт-контроллерах (app.php и app_dev.php):

$response = $kernel->handle($request);

Многие слушатели ожидают события ядра, как это было описано ранее, но включаются в работу лишь тогда, когда запрос имеет тип HttpKernelInterface::MASTER_REQUEST. Например, Firewall не будет ничего делать в случае, если запрос имеет тип подзапроса:

public function onKernelRequest(GetResponseEvent $event)
{
    if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
        return;
    }

    ...
}

Когда используются подзапросы?

Подзапросы используются для изоляции создания объекта ответа. Например, когда исключение перехвачено ядром, стандартный обработчик исключений пытается выполнить назначенный для этого исключения контроллер (см. предыдущую часть Обработка исключений). Для этого создаётся подзапрос:

public function onKernelException(GetResponseForExceptionEvent $event)
{
    $request = $event->getRequest();

    ...

    $request = $request->duplicate(null, null, $attributes);
    $request->setMethod('GET');

    $response = $event
        ->getKernel()
        ->handle($request, HttpKernelInterface::SUB_REQUEST, true);

    $event->setResponse($response);
}

Также каждый раз, когда вы рендерите контроллер через Twig-шаблон, создаётся и обрабатывается подзапрос:

{{ render(controller('BlogBundle:Post:list')) }}

Когда вы пишете собственный слушатель событий ядра…

Спросите себя, должен ли ваш слушатель реагировать на мастер-запрос, на подзапрос, или же на оба типа. И используйте условие для проверки, которое приведено выше.