Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
События ядра Symfony (Kernel Events)
Ядро Symfony представляет собой гибкую событийно-ориентированную архитектуру, которая позволяет перехватывать и обрабатывать ключевые моменты жизненного цикла запроса. События ядра — это мощный механизм для внедрения кастомной логики без модификации самого фреймворка. Они разделены на несколько категорий и типов.
Основные события ядра (HttpKernel)
Эти события относятся непосредственно к обработке HTTP.
1. kernel.request
Срабатывает в самом начале обработки запроса, до того, как контроллер будет определён. Основные use-cases:
- Модификация объекта
Request(например, добавление атрибутов). - Инициализация локали пользователя.
- Валидация и фильтрация входящих данных.
- Реализация механизма технического обслуживания (maintenance mode).
// Пример слушателя для kernel.request
class LocaleListener implements EventSubscriberInterface
{
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
$locale = $request->getSession()->get('_locale', 'en');
$request->setLocale($locale);
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}
2. kernel.controller
Срабатывает после выбора контроллера, но до его вызова. Идеально для:
- Внедрения аргументов в контроллер (например, через
@ParamConverterв Symfony или кастомные резолверы). - Логирования или аудита вызова конкретного действия.
- Проверки прав доступа на уровне метода контроллера (хотя обычно это делается через
kernel.requestили Security Voters).
// Пример: логирование вызова контроллера
public function onKernelController(ControllerEvent $event)
{
$controller = $event->getController();
// ... логика логирования
}
3. kernel.controller_arguments
Срабатывает после того, как аргументы для контроллера были разрешены, но до его вызова. Позволяет модифицировать финальный массив аргументов.
4. kernel.view
Срабатывает только если контроллер не возвращает объект Response, а возвращает какое-либо значение (массив, объект и т.д.). Задача слушателей этого события — преобразовать результат работы контроллера в объект Response. Это основа для компонента Serializer и механизма @Template в старых версиях.
// Пример: преобразование массива в JSON-ответ
public function onKernelView(ViewEvent $event)
{
$controllerResult = $event->getControllerResult();
if (is_array($controllerResult)) {
$response = new JsonResponse($controllerResult);
$event->setResponse($response);
}
}
5. kernel.response
Срабатывает после того, как контроллер вернул объект Response, но до его отправки клиенту. Используется для:
- Модификации ответа (добавление заголовков, сжатие контента).
- Внедрения CSS/JS в HTML-ответ (через компонент Webpack Encore или аналоги).
- Кэширования ответа.
// Пример: добавление кастомного заголовка
public function onKernelResponse(ResponseEvent $event)
{
$response = $event->getResponse();
$response->headers->set('X-Custom-Header', 'MyApp');
}
6. kernel.finish_request
Срабатывает после отправки ответа клиенту, но до вызова kernel.terminate. Полезен для очистки ресурсов, специфичных для данного запроса.
7. kernel.exception
Срабатывает при возникновении любого необработанного исключения в процессе обработки запроса. Ключевой инструмент для:
- Кастомной обработки ошибок (показ красивых страниц 404, 500).
- Логирования исключений.
- Преобразования исключений в специфичные HTTP-ответы (например, преобразование
AccessDeniedExceptionв ответ с кодом 403).
// Пример: обработка AccessDeniedException
public function onKernelException(ExceptionEvent $event)
{
$exception = $event->getThrowable();
if ($exception instanceof AccessDeniedException) {
$response = new Response('Доступ запрещён', 403);
$event->setResponse($response);
}
}
События терминации (kernel.terminate)
Это особое событие, которое срабатывает после отправки ответа клиенту (отправлены заголовки и тело). Работает только с быстрыми фронт-контроллерами (например, php-fpm). Идеально для «медленных» фоновых операций, которые не должны задерживать отправку ответа:
- Отправка email.
- Логирование в медленные хранилища.
- Обработка данных.
// Пример: отправка email после ответа
public function onKernelTerminate(TerminateEvent $event)
{
// Отправка email через асинхронный механизм
$this->mailer->send(...);
}
События консоли (ConsoleEvents)
Аналогичные события существуют и для консольных команд:
console.command— перед выполнением команды.console.terminate— после выполнения команды.console.error— при ошибке в команде.
Регистрация слушателей и подписчиков
Слушатели событий можно зарегистрировать двумя основными способами:
-
Через сервисы и тэги в
services.yaml(наиболее распространённый):services: App\EventListener\LocaleListener: tags: - { name: kernel.event_listener, event: kernel.request, priority: 20 } -
Через реализацию интерфейса
EventSubscriberInterface(более структурировано, позволяет объявить все события в одном методе):class MySubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => 'onKernelRequest', KernelEvents::RESPONSE => ['onKernelResponse', -10], ]; } // ... методы-обработчики }
Приоритеты (priority)
Очень важный аспект — порядок выполнения слушателей. Он определяется приоритетом (целое число). Чем выше число, тем раньше будет выполнен слушатель. Например, SecurityListener имеет высокий приоритет на событии kernel.request, чтобы проверка аутентификации прошла одной из первых.
Итог: Понимание событий ядра Symfony — это ключ к глубокой кастомизации фреймворка, созданию чистого, декларативного и переиспользуемого кода. Они позволяют грамотно встраиваться в жизненный цикл запроса, разделяя ответственность между модулями приложения.