Основные события в Symfony
Во время отрботки http-запроса framework Symfony генерирует некоторые события, которые можно обрабатывать, изменяя параметры запроса и ответа сервера.
Рассмотрим некторые из них.
Создание класса EventListener
Чтобы мы смогли перехватывать события нам необходимо создать специальный класс.
Создадим диркторию src/EventListener и в ней класс UserEventListener.
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\RequestEvent;
class UserEventListener
{
public function onKernelRequest(RequestEvent $event){
// ...
}
// ...
}
Его необходимо прописать в config/services.yaml с указанием всех событий, которые он будет перехватывать.
# config/services.yaml
App\EventListener\UserEventListener:
tags:
- {name: 'kernel.event_listener', event: 'kernel.request'}
- {name: 'kernel.event_listener', event: 'kernel.controller'}
- {name: 'kernel.event_listener', event: 'kernel.controller_arguments'}
- {name: 'kernel.event_listener', event: 'kernel.view'}
- {name: 'kernel.event_listener', event: 'kernel.response'}
Событие kernel.request
Вызывается очень рано, перед определением контроллера, который будет обрабатывать запрос.
Бывает полезным, когда нужно добавить в запрос какие-нибудь параметры или данные.
Параметром в функцию onKernelRequest передается событие Symfony\Component\HttpKernel\Event\RequestEvent.
Описание представлено ниже.
use Symfony\Component\HttpKernel\Event\RequestEvent;
class UserEventListener
{
public function onKernelRequest(RequestEvent $event){
$request = $event->getRequest();
// Можем добавить в запрос параметр
$request->request->set("event", "kernel request");
}
// ...
}
Событие kernel.controller
Данное событие вызывается до выполнения контоллера. При желании можно поменять контроллер для обработки. В качестве параметра в функцию onKernelController передается событие Symfony\Component\HttpKernel\Event\ControllerEvent.
use Symfony\Component\HttpKernel\Event\ControllerEvent;
class UserEventListener
{
public function onKernelController(ControllerEvent $event){
// Сменить контроллер для обработки
$controller = $event->setController(function()use($event){
return new Response("change controller");
});
}
}
Событие kernel.controller_arguments
Вызывается перед передачей аргументов в контроллер, удобно добавлять или изменять аргументы.
Тип передаваемого события: Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent.
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
class UserEventListener
{
public function onKernelControllerArguments(ControllerArgumentsEvent $event){
$event->setArguments([$event->getRequest(), ['myParam' => 'my_value']]);
}
}
Ниже представлено получение доступа к новым аргументам в контроллере.
В переменную $params передаются аргументы, добавленные в событии kernel.controller_arguments.
public function indexAction(Request $request, $params = false){
return $this->render('frontend/pages/index.html.twig', ['params' => $params]);
}
Событие kernel.view
Вызывается когда запрос уже обработан контроллером, но ответ не был отправлен.
Удобно использовать для установки стандартного ответа сервера в случае, когда контроллер не вернул ответ.
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpFoundation\Response;
class UserEventListener
{
public function onKernelView(ViewEvent $event){
$response = new Response();
$content = "Default page";
$response->setContent($content);
$event->setResponse($response);
}
}
Событие kernel.response
Событие происходит перед отправкой ответа клиенту.
Позволяет модифицировать Response, добавляя новые/изменяя headers, cookies
В качестве параметра в функцию onKernelResponse передается событие
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpFoundation\Cookie;
class UserEventListener
{
public function onKernelResponse(ResponseEvent $event){
$response = $event->getResponse();
$response->headers->setCookie(new Cookie('test_cookie', 'test_value'));
$event->setResponse($response);
}
}
Событие kernel.terminate
Данное событие происходит после обработки запроса и отправки ответа сервером.
На него удобно вешать "тяжелые" операции, чтобы пользователь долго не ждал ответ от сервера, например отправку почту, формирование бэкапов и т.д.
Класс события: Symfony\Component\HttpKernel\Event\TerminateEvent
use Symfony\Component\HttpKernel\Event\TerminateEvent;
class UserEventListener
{
public function onKernelTerminate(TerminateEvent $event){
// Любые тяжелые операции
}
}
Событие kernel.exception
Событие происходит при возникновении ошибки во время выполнения https запроса.
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
class UserEventListener
{
private $container;
public function __construct(Container $container){
$this->container = $container;
}
public function getContainer():?Container{
return $this->container;
}
public function onKernelException(ExceptionEvent $event){
$exception = $event->getThrowable();
if($exception instanceof NotFoundHttpException){
$path = $this->getContainer()->get('router')->generate("frontend_404");
$response = new RedirectResponse($path);
$event->setResponse($response);
}else{
$message = $this->getContainer()->get('twig')->render('frontend/error.html.twig', [
'error'=>$exception->getMessage()
]);
$response = new Response();
$response->setContent($message);
$response->setStatusCode(Response::HTTP_NOT_ACCEPTABLE);
$event->setResponse($response);
}
}
}