How to Implement Event Subscriber
Introduction
In this document, we will discuss how to implement an event subscriber in Drupal 9. We will provide a basic code example, explain its purpose, and discuss the possibilities of what can be achieved using event subscribers in Drupal.
What is an Event Subscriber?
Event subscribers in Drupal are a way to extend and modify the behavior of your application by listening to specific events dispatched by the system. They are part of the Symfony Event Dispatcher component, which is integrated into Drupal. By subscribing to events, you can react to changes in the system, perform additional actions, or modify the default behavior of certain operations.
Example of an Event Subscriber
<?php
namespace Drupal\anyModule\EventSubscriber; use Drupal\Core\Session\AccountProxy;
use Drupal\core_event_dispatcher\Event\Form\FormIdAlterEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\core_event_dispatcher\Event\Entity\EntityPresaveEvent;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Database\Connection; use Drupal\Core\Cache\Cache;
use Drupal\Core\File\FileSystem;
/**
* Any module Customization for event subscriber.
*/
class eventSubscriber implements EventSubscriberInterface {
/**
* Current user service.
*
* @var \Drupal\Core\Session\AccountProxy
*/ protected $currentUser;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/ protected $entityTypeManager;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* The file system.
*
* @var \Drupal\Core\File\FileSystem
*/ protected $fileSystem;
/**
* {@inheritdoc}
*/
public function __construct(AccountProxy $current_user, EntityTypeManager $entity_type_manager, Connection $connection, FileSystem $file_system) {
// Reference the current_user service.
$this->currentUser = $current_user;
$this->entityTypeManager = $entity_type_manager;
$this->connection = $connection;
$this->fileSystem = $file_system;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
'hook_event_dispatcher.form_node_form.alter' => 'alterMclNodeForm',
'hook_event_dispatcher.form_node_form.alter' => 'alterMclNodeForm',
];
}
/**
* Alter node form.
*
* @param \Drupal\core_event_dispatcher\Event\Form\FormIdAlterEvent $event
* The event.
*/
public function alterMclNodeForm(FormIdAlterEvent $event): void {
$form = &$event->getForm();
// This is a example: In a form you need to hide buttons for some reason or
//similar things, which cannot be done from the display form of the content type,
//we can do it from here:
$this->hiddenRemoveButtonOfMediaEntityTable($form);
// This method is example.
}
}
This would be the event subscriber, but take into account that this should ideally go inside a custom module that you have created for our specific need, the event subscriber by itself does not work, we must invoke it, and this is done in the services file .yml
Something like this:
services:
anyModule.event_subscriber:
class: Drupal\anyModule\EventSubscriber\EventSubscriber
arguments:
- "@current_user"
- "@entity_type.manager"
- "@database"
- "@file_system"
tags:
- { name: event_subscriber }
With this it should work, it is important to remember that we must clean the cache and activate our custom module, something like this:
- ddev drush on anyModule ( If you use lando is the same, "lando drush on anyModule")
- ddev drush cr ( If you use lando is the same, "lando drush cr")
Code from a site project that implements this functionality:
Use Cases and Possibilities
Event subscribers can be used for a wide variety of purposes in Drupal, including:
- Altering the forms
- Altering nodes.
- Responding to user authentication events
- etc,...
By using event subscribers, you can extend and customize your Drupal application to fit your specific needs, and react to various events happening throughout the system.
Here examples of original page of hook event dispatcher: https://github.com/pdenooijer/hook_event_dispatcher
Conclusion
The interesting thing about using this approach, instead of simply applying an alter hook or any hook in a .module, is how neat and simplified the code looks, since you can tidy up your code with the object-oriented programming structure and apply dependency injection and with it, call multiple services and everything will be easier to understand and it will look much better, for large projects, I think this is a very cool alternative that is worth trying.