Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Event Subscriber and Event Dispatcher. Working with events in Drupal

13/04/2025, by Ivan

Overview of Event Systems

Event systems are used in many complex applications as a way to allow extensions to alter the behavior of the system. An event system can be implemented in various ways, but the concepts and components that make up the system are generally the same.

  • Event Subscribers – sometimes called "listeners", are callable methods or functions that respond to an event dispatched throughout the event registry.
  • Event Registry – where event subscribers are collected and sorted.
  • Event Dispatcher – the mechanism by which an event is initiated or "dispatched" throughout the system.
  • Event Context – many events require a certain set of data that is important for the subscribers. This can be a simple value passed to the subscriber or something more complex like a dedicated class containing relevant data.

Drupal Hooks

For most of its existence, Drupal has had a rudimentary event system through "hooks". Let's see how the concept of hooks maps to the four components of an event system.

  • Event Subscribers – Drupal hooks are registered by defining a function with a specific name. For example, to subscribe to a "hook_my_event_name" event, you define a function like myprefix_my_event_name(), where "myprefix" is your module or theme name.
  • Event Registry – Drupal hooks are stored in the "cache_boostrap" bin under the identifier "module_implements". This is simply an array of modules that implement the hook, keyed by the hook name.
  • Event Dispatcher – hooks are dispatched differently in Drupal 7 and Drupal 8:
    • Drupal 7: via module_invoke_all()
    • Drupal 8: via \Drupal::moduleHandler()->invokeAll()
  • Event Context – context is passed to the subscriber through function parameters. For example:
    • Drupal 7: module_invoke_all('my_event_name', $some_arbitrary_parameter);
    • Drupal 8: \Drupal::moduleHandler()->invokeAll('my_event_name', [$some_arbitrary_parameter]);

Some downsides of the hook-based event approach:

  • Hooks are only registered during cache rebuilds. New hooks require cache rebuilding to be recognized.
  • Each module can only react to an event once. Because hooks rely on unique function names, each module or theme can only implement each hook once.
  • It’s hard to define event execution order. Drupal uses module weights to determine execution order. To override this, you must use "hook_module_implements_alter".

With Symfony integration in Drupal 8, a new event system exists. It's generally a better system and is increasingly used by contributed modules.

Drupal 8 Events

Drupal 8 events are very similar to Symfony events. Here's how they align with the event system components:

  • Event Subscribers – classes that implement \Symfony\Component\EventDispatcher\EventSubscriberInterface.
  • Event Dispatcher – a class implementing \Symfony\Component\EventDispatcher\EventDispatcherInterface. At least one instance is available as a service.
  • Event Registry – stored inside the dispatcher as an array with event names and priorities. Registering a subscriber as a service adds it to the dispatcher.
  • Event Context – a class extending \Symfony\Component\EventDispatcher\Event. Each event typically has its own custom class containing relevant data.

Learning to use events in Drupal 8 will improve your custom module development and prepare you for a future where events (hopefully) replace hooks.

My First Drupal 8 Event Subscriber

We'll create an event subscriber that displays a message when a Config object is saved or deleted.

Start by creating a module named custom_events:

name: Custom Events
type: module
description: Custom/Example event work.
core: 8.x
package: Custom

Register the event subscriber in custom_events.services.yml:

services:
  my_config_events_subscriber:
    class: '\Drupal\custom_events\EventSubscriber\ConfigEventsSubscriber'
    tags:
      - { name: 'event_subscriber' }

Then define the subscriber class in src/EventSubscriber/ConfigEventsSubscriber.php (see the original content for full code).

This subscriber listens to ConfigEvents::SAVE and ConfigEvents::DELETE, and logs messages via the Messenger service.

Sending Custom Events

Next, define your own event type, e.g. UserLoginEvent, extending Symfony’s Event class. Dispatch it in hook_user_login() via the event_dispatcher service.

Create another subscriber for this event (e.g. UserLoginSubscriber) to log a message when a user logs in, using $event->account to access the logged-in user.

Event Subscriber Priorities

Subscribers can define priorities to control execution order. A higher number means earlier execution.

public static function getSubscribedEvents() {
  return [
    ConfigEvents::SAVE => ['configSave', 100],
    ConfigEvents::DELETE => ['configDelete', -100],
  ];
}

Default priority is 0. By customizing priorities, you control which subscriber runs first or last.

References:

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.