How to define an Event in Drupal 8 – 9, What is Dispatcher and Subscriber in Drupal 8 – 9?

Event Subscribers – are callable methods or functions that react to an event using Event Registry.

Event Registry – This is the place where event subscribers. And collected and sorted.

Event Dispatcher – The mechanism in which an event is triggered/fired, or “dispatched”, throughout the system.

Event Context – Many events require specific set of data that is important to the subscribers to an event. This can be as simple as a value passed to the Event Subscriber, or as complex as a specially created class that contains the relevant data.

in this article we will do learn:

How to define an event in Drupal 8? / How to define an event in Drupal 9?
How to dispatch the event in Drupal 8? / How to dispatch the event in Drupal 9?
How to subscribe an event in Drupal 8? / How to subscribe an event in Drupal9?

Let’s see small example, when user login into system, user able to know when it get registered.

How to define an Event in Drupal 8 – 9. And what is Dispatcher and Subscriber in Drupal 8 – 9 step by step:

First we will create custom module and for that we will create  .info.yml for our module called ‘events_example’ , which is events_example.info.yml

Create Drupal 9 custom module

name: Events Example
type: module
description: Events Example module for Event handling in Drupal 8 - 9.
package: custom
version: 1.0
core_version_requirement: ^8.7.7 || ^9
Install Event Subscriber module
Install Event Subscriber module

How to define an Event in Drupal 8 – 9.

  • Create src directory inside your module : /src
  • Create Event directory inside your module : /src/Event
  • Create Class name “UserLoginEvent.php”
  • Past the below code inside “UserLoginEvent.php”
<?php

namespace Drupal\events_example\Event;

use Drupal\user\UserInterface;
use Symfony\Component\EventDispatcher\Event;

/**
 * Event that is fired when a user logs in.
 */
class UserLoginEvent extends Event {

  const EVENT_NAME = 'events_example_user_login';

  /**
   * The user account.
   *
   * @var \Drupal\user\UserInterface
   */
  public $account;

  /**
   * Constructs the object.
   *
   * @param \Drupal\user\UserInterface $account
   *   The account of the user logged in.
   */
  public function __construct(UserInterface $account) {
    $this->account = $account;
  }

}
  • we have defined namespace of this class: namespace Drupal\events_example\Event
  • We used UserInterface to get user data, like Name etc. : use Drupal\user\UserInterface
  • here UserLoginEvent Class extends Event which is symfony component : use Symfony\Component\EventDispatcher\Event
  • Here we declared constructor to load all data in this. You can create your own function here too, which can be accessed whenever dispatching the event or in subscriber call back.

How to dispatch the event in Drupal 8? / How to dispatch the event in Drupal 9?

  • Create EventSubscriber directory inside your module : path will be : /src/EventSubscriber
  • Create Class name “ConfigEventsSubscriber.php” and path will be: src/EventSubscriber/ConfigEventsSubscriber.php
  • Past the below code inside “ConfigEventsSubscriber.php”
<?php

namespace Drupal\events_example\EventSubscriber;

use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Class EntityTypeSubscriber.
 *
 * @package Drupal\events_example\EventSubscriber
 */
class ConfigEventsSubscriber implements EventSubscriberInterface {
  /**
   * {@inheritdoc}
   *
   * @return array
   *   The event names to listen for, and the methods that should be executed.
   */
  public static function getSubscribedEvents() {
    return [
      ConfigEvents::SAVE => 'configSave',
      ConfigEvents::DELETE => 'configDelete',
    ];
  }

  /**
   * React to a config object being saved.
   *
   * @param \Drupal\Core\Config\ConfigCrudEvent $event
   *   Config crud event.
   */
  public function configSave(ConfigCrudEvent $event) {
    $config = $event->getConfig();
    \Drupal::messenger()->addStatus('Saved config: ' . $config->getName());
  }

  /**
   * React to a config object being deleted.
   *
   * @param \Drupal\Core\Config\ConfigCrudEvent $event
   *   Config crud event.
   */
  public function configDelete(ConfigCrudEvent $event) {
    $config = $event->getConfig();
    \Drupal::messenger()->addStatus('Deleted config: ' . $config->getName());
  }

}
  • namespace Drupal\events_example\EventSubscriber it is namespace of class. Thru which we can easily access it.
  • we used use Symfony\Component\EventDispatcher\EventSubscriberInterface; EventSubscriberInterface
  • We implement the getSubscribedEvents() method of interface EventSubscriberInterface. That method returns an array of event name => method name as a key/value pairs.
  • use Drupal\Core\Config\ConfigCrudEvent; Thru which we can use configSave() and configDelete() method, and also it has getConfig method which return object of this config.
  • ConfigEvents::SAVE => ‘configSave’, is defined globally to access from anywhere. it mean SAVE has value config.save
Config Update message when updated the Basic site settings
Config Update message when updated the Basic site settings

Create module_name.module file.

We will add hook for dispatch our event. for that we’re going to create module_name.module file where we use “hook_user_login”. Method start by creating events_example.module inside your module. And past the below code.

<?php

/**
 * @file
 * Contains events_example.module.
 */

use Drupal\events_example\Event\UserLoginEvent;
use \Drupal\user\UserInterface;
/**
 * Implements hook_user_login().
 */
function events_example_user_login($account) {

  // Instantiate our event.
  $event = new UserLoginEvent($account);

  // Get the event_dispatcher service and dispatch the event.
  $event_dispatcher = \Drupal::service('event_dispatcher');
  $event_dispatcher->dispatch(UserLoginEvent::EVENT_NAME, $event);
}

Inside of our “events_example_user_login” here events_example will be your module name. Implementation, we only need to do a few things to dispatch our new event:

  • Instantiate a new custom object named UserLoginEvent and provide its constructor the $account object available within the hook.
  • Using services load event_dispatcher service.
  • Execute the dispatch() method on the event_dispatcher service. Provide the name of the event we’re dispatching (UserLoginEvent::EVENT_NAME), and the event object we just created ($event).

Create .services.yml file

Here, Create events_example.services.yml inside your module.

services:
  events_example.event_subscriber_test:
    class: Drupal\events_example\EventSubscriber\ConfigEventsSubscriber
    tags:
      - { name: 'event_subscriber' }

  # Subscriber to the event we dispatch in hook_user_login.
  events_example_user_login:
    class: '\Drupal\events_example\EventSubscriber\UserLoginSubscriber'
    tags:
      - { name: 'event_subscriber' }

Here, we can define many services, as per our need.

  • Name of services: events_example.event_subscriber_test
  • Class of services.
  • Tags of services.

How to dispatch the event in Drupal 8? | How to dispatch the event in Drupal 9?

  • Create EventSubscriber directory inside your module : path will be : /src/EventSubscriber
  • Create Class name “UserLoginSubscriber.php and path will be: src/EventSubscriber/UserLoginSubscriber.php
  • Past the below code inside “UserLoginSubscriber.php”
<?php

namespace Drupal\events_example\EventSubscriber;

use Drupal\events_example\Event\UserLoginEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Class UserLoginSubscriber.
 *
 * @package Drupal\events_example\EventSubscriber
 */
class UserLoginSubscriber implements EventSubscriberInterface {

  /**
   * Database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * Date formatter.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      // Static class constant => method on this class.
      UserLoginEvent::EVENT_NAME => 'onUserLogin',
    ];
  }

  /**
   * Subscribe to the user login event dispatched.
   *
   * @param \Drupal\custom_events\Event\UserLoginEvent $event
   *   Dat event object yo.
   */
  public function onUserLogin(UserLoginEvent $event) {
    $database = \Drupal::database();
    $dateFormatter = \Drupal::service('date.formatter');

    $account_created = $database->select('users_field_data', 'ud')
      ->fields('ud', ['created'])
      ->condition('ud.uid', $event->account->id())
      ->execute()
      ->fetchField();

     $userName  = $event->account->getAccountName();


    \Drupal::messenger()->addStatus(t('Welcome : '.$userName.', your account was created on %created_date.', [
      '%created_date' => $dateFormatter->format($account_created, 'short'),
    ]));
  }

}
After Login, You can check message.
After Login, You can check message.
  • I have subscribed to the event named UserLoginEvent::EVENT_NAME with the method onUserLogin() (a method name we made up).
  • During onUserLogin, we access the $account property (the user that just logged in) of the $event object, and do some stuff with it: like print user name and login date and time.
  • When a user logs in, they should see a message telling them the date and time for when they joined the site.

Pradip Mehta

I am a well-organized professional in Drupal Development and PHP web development with strong script handling knowledge or automation process with PHP. I have advanced computer skills and am a proficient multitasker.