Какие события ядра (Kernel Events) существуют в Symfony?

«Какие события ядра (Kernel Events) существуют в Symfony?» — вопрос из категории Symfony, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ядро Symfony (HttpKernel) генерирует ряд событий на протяжении жизненного цикла обработки HTTP-запроса. Эти события позволяют внедрять кастомную логику на разных этапах. Основные события определены в классе SymfonyComponentHttpKernelKernelEvents.

Полный список основных событий ядра:

  1. KernelEvents::REQUEST (kernel.request):

    • Когда: Сразу после получения Request от фронт-контроллера (index.php), но до определения роута и контроллера.
    • Зачем: Для глобальной инициализации, локализации, ранней проверки прав доступа (например, брандмауэр безопасности слушает это событие).
  2. KernelEvents::CONTROLLER (kernel.controller):

    • Когда: После определения контроллера и аргументов, но непосредственно перед его вызовом.
    • Зачем: Для модификации контроллера (например, подмена на другой) или его аргументов (например, десериализация тела запроса в объект).
  3. KernelEvents::CONTROLLER_ARGUMENTS (kernel.controller_arguments):

    • Когда: После разрешения всех аргументов контроллера, но перед вызовом.
    • Зачем: Для последней проверки или модификации массива аргументов.
  4. KernelEvents::VIEW (kernel.view):

    • Когда: Если контроллер вернул значение, которое не является объектом Response.
    • Зачем: Чтобы преобразовать результат контроллера (массив, объект) в Response. За это отвечает, например, SymfonyBundleFrameworkBundleControllerAbstractController.
  5. KernelEvents::RESPONSE (kernel.response):

    • Когда: После того как у ядра есть объект Response (полученный от контроллера или сформированный в VIEW), но перед его отправкой.
    • Зачем: Для модификации ответа — добавление заголовков, сжатие GZIP, инъекция контента.
  6. KernelEvents::FINISH_REQUEST (kernel.finish_request):

    • Когда: Сразу после RESPONSE, когда основной запрос завершен. Используется для очистки контекстозависимых данных (например, локали в RequestContext).
  7. KernelEvents::TERMINATE (kernel.terminate):

    • Когда: После отправки ответа клиенту (соединение закрыто).
    • Зачем: Для выполнения задач, которые не должны задерживать отправку ответа: тяжелое логирование, отправка email, обработка очередей.
  8. KernelEvents::EXCEPTION (kernel.exception):

    • Когда: При возникновении любого необработанного исключения в процессе работы ядра.
    • Зачем: Для кастомной обработки ошибок — преобразование исключения в пользовательскую страницу ошибки, логирование, отправку уведомлений.

Пример слушателя для логирования исключений:

# config/services.yaml
services:
    AppEventListenerExceptionLoggerListener:
        tags:
            - { name: kernel.event_listener, event: kernel.exception, priority: 100 }
// src/EventListener/ExceptionLoggerListener.php
use PsrLogLoggerInterface;
use SymfonyComponentHttpKernelEventExceptionEvent;

class ExceptionLoggerListener
{
    public function __construct(private LoggerInterface $logger) {}

    public function onKernelException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();
        $this->logger->error('Unhandled exception', [
            'exception' => $exception,
            'url' => $event->getRequest()->getUri(),
        ]);
        // Можно НЕ останавливать распространение события,
        // чтобы стандартный обработчик ошибок Symfony тоже сработал.
    }
}