logo

Extra Block Types (EBT) - Nieuwe Layout Builder ervaring❗

Extra Block Types (EBT) - gestileerde, aanpasbare bloktypes: Slideshows, Tabs, Cards, Accordions en vele andere. Ingebouwde instellingen voor achtergrond, DOM Box, javascript-plugins. Ervaar vandaag al de toekomst van layout building.

Demo EBT-modules Download EBT-modules

❗Extra Paragraph Types (EPT) - Nieuwe Paragraphs ervaring

Extra Paragraph Types (EPT) - analoge op paragrafen gebaseerde set modules.

Demo EPT-modules Download EPT-modules

Scroll

Event Subscriber en Event Dispatcher. Het systeem voor werken met events in Drupal.

03/10/2025, by Ivan

Menu

Overzicht van het eventsysteem

Eventsystemen worden in veel complexe applicaties gebruikt als een manier om extensies toe te laten de werking van het systeem te beïnvloeden. Een eventsysteem kan op verschillende manieren geïmplementeerd worden, maar over het algemeen zijn de concepten en componenten waaruit zo’n systeem bestaat hetzelfde.

  • Event Subscribers – soms ook “listeners” genoemd, zijn aanroepbare methoden of functies die reageren op een event dat door het hele eventregister wordt verspreid.
  • Event Registry – de plaats waar event-subscribers verzameld en gesorteerd worden.
  • Event Dispatcher – het mechanisme waarmee een event wordt geïnitieerd of “uitgezonden” door het systeem.
  • Event Context – veel events vereisen een bepaalde set gegevens die belangrijk zijn voor de event-subscribers. Dit kan een eenvoudige waarde zijn die aan de subscriber wordt doorgegeven, of iets complexers zoals een speciaal gemaakte klasse die de relevante data bevat.

Drupal Hooks

Gedurende het grootste deel van zijn bestaan had Drupal een rudimentair eventsysteem via “hooks”. Laten we eens kijken hoe het concept “hooks” zich verhoudt tot deze 4 elementen van een eventsysteem.

  • Event Subscribers – Drupal hooks worden geregistreerd door een functie met een specifieke naam te definiëren. Bijvoorbeeld, als u zich wilt abonneren op het event “hook_my_event_name”, moet u een nieuwe functie definiëren met de naam myprefix_my_event_name(), waarbij “myprefix” de naam van uw module of thema is.
  • Event Registry – Drupal hooks worden opgeslagen in de “cache_bootstrap”-container onder de ID “module_implements”. Dit is eenvoudigweg een array van modules die de hook implementeren, aangeduid door de naam van de hook.
  • Event Dispatcher – hooks worden op verschillende manieren uitgevoerd in Drupal 7 en Drupal 8:

1) Drupal 7: hooks worden aangeroepen met de functie module_invoke_all()
2) Drupal 8: hooks worden aangeroepen via de servicemethode \Drupal::moduleHandler()->invokeAll().

  • Event Context – de context wordt aan de subscriber doorgegeven via parameters. Bijvoorbeeld, deze dispatcher voert alle implementaties van “hook_my_event_name” uit en geeft de parameter $some_arbitrary_parameter door:

1) Drupal 7: module_invoke_all('my_event_name', $some_arbitrary_parameter);
2) Drupal 8: \Drupal::moduleHandler()->invokeAll('my_event_name', [$some_arbitrary_parameter]);

Nadelen van de hook-aanpak voor events:

  • Registreert events alleen bij cache-rebuild. Nieuwe hooks worden pas opgepikt na het opnieuw opbouwen van bepaalde caches.
  • Elke module kan maar één keer op een event reageren. Omdat de implementatie gebonden is aan een functienaam, kan een module of thema slechts één implementatie hebben per event.
  • De volgorde van event-uitvoering is lastig te bepalen. Drupal bepaalt de volgorde van event-subscribers aan de hand van module-gewichten. Een latere oplossing in Drupal 7 was “hook_module_implements_alter”.

Met Symfony in Drupal 8 is er nu een ander systeem van events – meestal beter. Hoewel de core van Drupal 8 niet veel events uitzendt, maken veel modules er al gebruik van.

Drupal 8 Events

Drupal 8-events lijken sterk op Symfony-events. Laten we kijken hoe dit zich verhoudt tot de componenten van het eventsysteem:

  • Event Subscribers – een klasse die \Symfony\Component\EventDispatcher\EventSubscriberInterface implementeert.
  • Event Dispatcher – een klasse die \Symfony\Component\EventDispatcher\EventDispatcherInterface implementeert. Meestal is er minstens één dispatcher beschikbaar als service, maar extra dispatchers zijn mogelijk.
  • Event Registry – de registry van subscribers wordt bijgehouden in de Event Dispatcher als een array met de naam van het event en prioriteit (volgorde).
  • Event Context – een klasse die \Symfony\Component\EventDispatcher\Event uitbreidt. Meestal creëert elke uitbreiding die zijn eigen event uitzendt een nieuwe Event-klasse die de benodigde data bevat.

Het leren gebruiken van Drupal 8-events helpt u bij het ontwikkelen van custom modules en bereidt u voor op de toekomst, waarin events (hopelijk) hooks vervangen.

Mijn eerste Drupal 8 Event Subscriber

Laten we een eerste subscriber maken die reageert op core events. Bijvoorbeeld, we willen een subscriber die een bericht toont wanneer een Config-object wordt opgeslagen of verwijderd.

Eerst maken we een module custom_events met een info.yml bestand:

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

Daarna registreren we onze subscriber in custom_events.services.yml:

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

Nu schrijven we de klasse ConfigEventsSubscriber die EventSubscriberInterface implementeert. Deze reageert op ConfigEvents::SAVE en ConfigEvents::DELETE.

namespace Drupal\custom_events\EventSubscriber;

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

class ConfigEventsSubscriber implements EventSubscriberInterface {

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

  public function configSave(ConfigCrudEvent $event) {
    $config = $event->getConfig();
    \Drupal::messenger()->addStatus('Saved config: ' . $config->getName());
  }

  public function configDelete(ConfigCrudEvent $event) {
    $config = $event->getConfig();
    \Drupal::messenger()->addStatus('Deleted config: ' . $config->getName());
  }
}

Telkens wanneer een config-object wordt opgeslagen of verwijderd, toont Drupal een bericht.

Mijn eerste custom event en dispatching

We creëren een nieuw event UserLoginEvent dat wordt verstuurd bij hook_user_login().

namespace Drupal\custom_events\Event;

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

class UserLoginEvent extends Event {
  const EVENT_NAME = 'custom_events_user_login';
  public $account;

  public function __construct(UserInterface $account) {
    $this->account = $account;
  }
}

In custom_events.module:

use Drupal\custom_events\Event\UserLoginEvent;

function custom_events_user_login($account) {
  $event = new UserLoginEvent($account);
  $dispatcher = \Drupal::service('event_dispatcher');
  $dispatcher->dispatch(UserLoginEvent::EVENT_NAME, $event);
}

Daarna maken we een subscriber UserLoginSubscriber die luistert naar UserLoginEvent::EVENT_NAME en een welkomstbericht toont.

Prioriteiten van event-subscribers

In tegenstelling tot hooks kunt u in het event-systeem prioriteiten instellen per subscriber. Hoe hoger de prioriteit, hoe eerder de subscriber wordt uitgevoerd. Zonder expliciete prioriteit is de standaardwaarde 0.

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

Hiermee wordt configSave eerst uitgevoerd (prioriteit 100) en configDelete pas na andere subscribers (prioriteit -100).

Referenties