Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

События и подписчики

Событие — сообщение «сейчас произошло то-то», которое ядро рассылает всем желающим. Подписчик — класс, который слушает нужные события и выполняет свой код. Это второй, наряду с хуками, способ вмешаться в работу Drupal. Событиями оформлена та часть ядра, что пришла из Symfony: обработка запроса и ответа, маршруты, сохранение настроек.

Где лежит подписчик

Подписчики принято класть в папку src/EventSubscriber модуля. Создайте папку и файл вручную.

Класс подписчика

Добавим ко всем ответам сайта свой заголовок:

// web/modules/custom/blog/src/EventSubscriber/HeaderSubscriber.php
namespace Drupal\blog\EventSubscriber;
 
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
 
class HeaderSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => 'onResponse'];
    }
 
    public function onResponse(ResponseEvent $event): void
    {
        $event->getResponse()->headers->set('X-Blog', 'Drupal course');
    }
}

Метод getSubscribedEvents() сообщает, какие события слушать и какой метод вызывать. KernelEvents::RESPONSE происходит, когда ответ готов к отправке. В метод приходит объект события — из него получают ответ и меняют его.

Регистрация

Подписчик — это сервис с особой меткой. Добавьте его в blog.services.yml:

# web/modules/custom/blog/blog.services.yml
services:
  blog.header_subscriber:
    class: Drupal\blog\EventSubscriber\HeaderSubscriber
    tags:
      - { name: event_subscriber }

Метка event_subscriber в разделе tags сообщает Drupal, что сервис нужно подключить к рассылке событий. Если в файле уже есть раздел services, новую запись добавляют в него, не повторяя слово services.

Проверка

vendor/bin/drush cr
curl -I http://127.0.0.1:8888/blog

В заголовках ответа появится строка X-Blog: Drupal course. Она же видна в инструментах разработчика браузера на вкладке «Сеть».

Частые события

СобытиеКогда происходит
KernelEvents::REQUESTЗапрос получен, контроллер ещё не выбран
KernelEvents::RESPONSEОтвет готов к отправке
KernelEvents::EXCEPTIONВо время обработки возникло исключение
ConfigEvents::SAVEСохранён объект конфигурации
RoutingEvents::ALTERСобран список маршрутов: можно изменить чужой маршрут

Классы ConfigEvents и RoutingEvents находятся в пространствах имён Drupal\Core\Config и Drupal\Core\Routing.

Приоритет

Если на событие подписано несколько классов, порядок задаёт приоритет — число рядом с именем метода:

// web/modules/custom/blog/src/EventSubscriber/HeaderSubscriber.php
public static function getSubscribedEvents(): array
{
    return [KernelEvents::RESPONSE => ['onResponse', 100]];
}

Чем больше число, тем раньше вызывается подписчик. Без числа приоритет равен нулю.

Хук или событие

Выбирать не приходится: способ определяет ядро. Сущности, формы и шаблоны расширяются хуками, а запрос, ответ, маршруты и конфигурация — событиями. В документации каждого места указано, что именно оно предлагает.

Частая ошибка

Класс подписчика написан, а метод не вызывается. Причина — подписчик не зарегистрирован: Drupal не ищет такие классы по папке, как плагины. Нужна запись в blog.services.yml с меткой event_subscriber и затем drush cr. Проверьте и отступы в YAML: tags стоит на том же уровне, что class.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.