Events and subscribers
An event is a message saying "this has just happened" that core sends to everyone interested. A subscriber is a class that listens to the events it needs and runs its own code. Next to hooks, it is the second way to step into the work of Drupal. Events are used by the part of core that came from Symfony: handling the request and response, routes, saving configuration.
Where a subscriber lives
Subscribers go to the src/EventSubscriber folder of the module by convention. Create the folder and the file by hand.
The subscriber class
Let us add a header to every response of the site:
// 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');
}
}The getSubscribedEvents() method says which events to listen to and which method to call. KernelEvents::RESPONSE happens when the response is ready to be sent. The method receives the event object — the response is taken from it and changed.
Registering
A subscriber is a service with a special tag. Add it to blog.services.yml:
# web/modules/custom/blog/blog.services.yml
services:
blog.header_subscriber:
class: Drupal\blog\EventSubscriber\HeaderSubscriber
tags:
- { name: event_subscriber }The event_subscriber tag in the tags section tells Drupal to connect the service to event dispatching. If the file already has a services section, the new entry is added to it without repeating the word services.
Checking
vendor/bin/drush cr
curl -I http://127.0.0.1:8888/blogThe response headers now contain the line X-Blog: Drupal course. It is also visible in the browser developer tools on the Network tab.
Frequent events
| Event | When it happens |
|---|---|
KernelEvents::REQUEST | The request has arrived, the controller is not chosen yet |
KernelEvents::RESPONSE | The response is ready to be sent |
KernelEvents::EXCEPTION | An exception was thrown during handling |
ConfigEvents::SAVE | A configuration object was saved |
RoutingEvents::ALTER | The list of routes is built: another module's route can be changed |
The ConfigEvents and RoutingEvents classes are in the Drupal\Core\Config and Drupal\Core\Routing namespaces.
Priority
If several classes subscribe to an event, the order is set by the priority — a number next to the method name:
// web/modules/custom/blog/src/EventSubscriber/HeaderSubscriber.php
public static function getSubscribedEvents(): array
{
return [KernelEvents::RESPONSE => ['onResponse', 100]];
}The larger the number, the earlier the subscriber is called. Without a number the priority is zero.
Hook or event
You do not have to choose: core decides. Entities, forms and templates are extended with hooks, while the request, response, routes and configuration use events. The documentation of each place says what exactly it offers.
Common mistake
The subscriber class is written, but the method is not called. The cause is that the subscriber is not registered: Drupal does not look for such classes by folder, as it does for plugins. You need an entry in blog.services.yml with the event_subscriber tag and then drush cr. Check the YAML indentation too: tags is on the same level as class.