Какие события (Events) существуют в системе Event Dispatcher?

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

Ответ

Концепция Event Dispatcher (диспетчера событий) является паттерном, и конкретные события зависят от фреймворка или приложения. В контексте Symfony (как эталонной реализации для PHP) можно выделить несколько категорий встроенных событий:

1. События Ядра (HttpKernel): Обрамляют жизненный цикл HTTP-запроса.

  • KernelEvents::REQUEST (kernel.request): Вызывается в самом начале запроса. Используется для инициализации, проверки прав доступа глобально.
  • KernelEvents::CONTROLLER (kernel.controller): Вызывается непосредственно перед вызовом контроллера. Позволяет изменить контроллер или аргументы (например, для преобразования данных запроса в DTO).
  • KernelEvents::VIEW (kernel.view): Вызывается, если контроллер вернул не объект Response, а какие-то данные. Позволяет преобразовать эти данные в Response.
  • KernelEvents::RESPONSE (kernel.response): Вызывается перед отправкой ответа клиенту. Позволяет модифицировать Response (добавить заголовки, сжать контент).
  • KernelEvents::FINISH_REQUEST (kernel.finish_request): Вызывается после создания ответа, когда основной запрос обработан.
  • KernelEvents::TERMINATE (kernel.terminate): Вызывается после отправки ответа клиенту. Идеально для «тяжелых» фоновых задач (логирование, отправка email), чтобы не задерживать ответ.
  • KernelEvents::EXCEPTION (kernel.exception): Вызывается при возникновении необработанного исключения. Используется для кастомной обработки ошибок.

2. События Консоли (Console): Аналогичны событиям ядра, но для CLI-команд.

  • ConsoleEvents::COMMAND, ConsoleEvents::TERMINATE, ConsoleEvents::ERROR.

3. События Компонентов: Другие компоненты Symfony генерируют свои события (например, FormEvents, SecurityEvents).

4. Пользовательские события: Разработчик может создавать свои классы событий для бизнес-логики (например, OrderPlacedEvent, UserRegisteredEvent).

Пример подписки в Symfony через атрибуты:

use SymfonyComponentHttpKernelEventResponseEvent;
use SymfonyComponentEventDispatcherAttributeAsEventListener;

#[AsEventListener(event: KernelEvents::RESPONSE)]
class AddSecurityHeadersListener
{
    public function __invoke(ResponseEvent $event): void
    {
        $response = $event->getResponse();
        $response->headers->set('X-Content-Type-Options', 'nosniff');
        $response->headers->set('X-Frame-Options', 'DENY');
    }
}