Система events позволяет строить более сложные системы с возможностью изменения функционала с помощью кастомного кода по определенным событиям. Многие хуки из Drupal 7 были заменены event'ами. Это позволило унифицировать работу многих частей друпала и дополнительных контрибных модулей. Сама система events пришла из Symfony и состоит из следующих частей:
Event Subscribers - "Подписчики" на определенные события, это функции или методы, которые срабатывают по определенным событиям. В коде является классом, который реализует класс:
\Symfony\Component\EventDispatcher\EventSubscriberInterface
Event Registry - Собирает и сортирует по очередности срабатывания Event Subscribers. Registry для subscribers хранимых в объекте Event Dispatcher'а как массив ключ-значение имени события и приоритет события (порядок). Когда событие регистрируется как service, событие регистрируется как глобально доступный dispatcher.
Event Dispatcher - Механизм в котором событие срабатывает и позволяет вызывать в нужный момент Event Subscribers. Главным образом по меньшей мере один из экземляров Event Dispatcher'a представлен как service. Класс Event Dispatcher'a реализует: \Symfony\Component\EventDispatcher\EventDispatcherInterface.
Event Context - Многие события требуют специфического набора данных, что может быть вазжно для subscriber'а на event. Это может быть простое значение переданное в Event Subscriber, а может быть и класс который содержит нужные данные. Класс Event Context расширяет класс: \Symfony\Component\EventDispatcher\Event.
Давайте разберем примеры работы с событиями, чтобы стало понятно как это работает.
Я добавил весь код на github в модуль drupalbook_examples, вы можете скачать модуль и добавить его к себе на сайт:
https://github.com/levmyshkin/drupalbook8
В Drupal 8 больше нет hook_init():
https://www.drupal.org/node/2013014
Теперь выполнить нужный код при загрузке страницы можно с помощью Event Subscriber'a:
modules/custom/drupalbook_examples/drupalbook_examples.services.yml
services: drupalbook_examples.event_subscriber: class: Drupal\drupalbook_examples\EventSubscriber\DrupalbookExamplesSubscriber tags: - {name: event_subscriber}
Для того чтобы подключить Event Subscriber нужно добавить сервис в файл модуля *.services.yml. Здесь мы описываем какой класс будет Event subscriber'ом и пишем в тегах имя event_subscriber. Теперь нужно создать класс event subscriber:
modules/custom/drupalbook_examples/src/EventSubscriber/DrupalbookExamplesSubscriber.php
<?php namespace Drupal\drupalbook_examples\EventSubscriber; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class DrupalbookExamplesSubscriber implements EventSubscriberInterface { public function checkForRedirection(GetResponseEvent $event) { if ($event->getRequest()->query->get('redirect-me')) { $event->setResponse(new RedirectResponse('http://example.com/')); } } /** * {@inheritdoc} */ public static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = array('checkForRedirection'); return $events; } }
Давайте разберем основные моменты этого кода. Класс нашего event subscriber реализует интерфейс EventSubscriberInterface, основным методом этого интерфейса является getSubscribedEvents(), он определяет на какие события будет реагировать наш subscriber и какие методы он будет вызывать в случае если событие произойдет. В нашем случает событие произойдет при самом начале работы друпала после обработки запроса. Здесь мы вызывает метод checkForRedirection() если происходит событие. В самом методе если у нас есть get параметр redirect-me, то перенаправляет пользователя на сайт example.com.
Этот код будет работать, всегда когда вы будете загружать страницу, ну или почти всегда. Дело в том, если ваша страница закеширована, то она может быть отдана из кеша и друпал не будет отрабатывать все куски кода и сразу сработает кеш. В этом случае можно использовать аналог хука hook_boot(), который также как и hook_init() удален из Drupal 8:
https://www.drupal.org/node/1909596
Давайте добавим еще метод redirectBeforeWithoutCache()
modules/custom/drupalbook_examples/src/EventSubscriber/DrupalbookExamplesSubscriber.php:
<?php namespace Drupal\drupalbook_examples\EventSubscriber; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class DrupalbookExamplesSubscriber implements EventSubscriberInterface { public function checkForRedirection(GetResponseEvent $event) { if ($event->getRequest()->query->get('redirect-me')) { $event->setResponse(new RedirectResponse('http://example.com/')); } } public function redirectBeforeWithoutCache(GetResponseEvent $event) { if ($event->getRequest()->query->get('redirect-me')) { $event->setResponse(new RedirectResponse('http://example.com/')); } } /** * {@inheritdoc} */ public static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = array('checkForRedirection'); $events[KernelEvents::REQUEST][] = array('redirectBeforeWithoutCache', 300); return $events; } }
В методе getSubscribedEvents() мы зарегистрировали ответ на тоже событие KernelEvents::REQUEST, только в этом случае мы установили приоритет 300, что позволяет сработать этому методу раньше, чем методы которые сработают для этого события, но у которых меньший приоритет. Теперь редирект сработает даже для закешированной страницы.
В друпале довольно много событий, которые можно добавить в Subscriber, больше примеров вы сможете найти в официальной документации:
https://www.drupal.org/docs/8/creating-custom-modules/event-systems-overview-how-to-subscribe-to-and-dispatch-events
Добавить комментарий