For most of its existence Drupal has had a rudimentary events system by the way of "hooks". With the foundation of Symfony in Drupal 8, there is now another events system in play. A better events system in most ways. While there are not a lot of events dispatched in Drupal 8 core, plenty of modules have started making use of this system.
In this tutorial we are going to create an event subscriber and then an event dispatcher.
Build a custom Event Subscriber
First create a module, easiest using the drupal console.
drupal generate:module
Then we need to create a services yaml file, in this case my_demo.services.yml, this file tells Drupal about out event subsriber.
services:
my_config_events_subscriber:
class: '\Drupal\my_demo\EventSubscriber\ConfigEventsSubscriber'
tags:
- { name: 'event_subscriber' }
Then create a services class, ConfigEventsSubscriber.php.
<?php
namespace Drupal\my_demo\EventSubscriber;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class EntityTypeSubscriber.
*
* @package Drupal\custom_events\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());
}
}
This bit of code is the important bit:
public static function getSubscribedEvents() {
return [
ConfigEvents::SAVE => 'configSave',
ConfigEvents::DELETE => 'configDelete',
];
}
This is telling Drupal that when the save config event and delete config events occur, we want to call our custom functions.
Then on save we run this code:
public function configSave(ConfigCrudEvent $event) {
$config = $event->getConfig();
\Drupal::messenger()->addStatus('Saved config: ' . $config->getName());
}
This is simple, just going to display a message that tells us when a config value is saved.
Then we enable the my_demo module and after that enable another module, for example stats. The we can see that our custom subsribed events have triggered.
The core.extension config is update to reflect the module has been enabled, and the statistics.settings is the new config for the module.
Build a custom Event Dispatcher
First we need to create an event class as src/Event/UserLoginEvent.php as follows.
<?php
namespace Drupal\my_demo\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 = 'my_demo_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;
}
}
Then we need to trigger this event from the user login code, as below:
function my_demo_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);
}
So you see the EVENT_NAME constant within the event class we created can be anything to description the event, and is used as the identifier to trigger the event. Finally we need to subscribe to that event and do something:
In my_demo.services.yml add the subscribe info:
services:
my_demo_user_login:
class: '\Drupal\my_demo\EventSubscriber\UserLoginSubscriber'
tags:
- { name: 'event_subscriber' }
Then finally write the subscribe and output the account created date in a message which show when we login.
<?php
namespace Drupal\my_demo\EventSubscriber;
use Drupal\my_demo\Event\UserLoginEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class UserLoginSubscriber.
*
* @package Drupal\custom_events\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();
\Drupal::messenger()->addStatus(t('Welcome, your account was created on %created_date.', [
'%created_date' => $dateFormatter->format($account_created, 'short'),
]));
}
}
That's it. We have created a custom event dispatcher and subscribed to it the result being the below.
Add new comment