Until TYPO3 9 LTS, we were using Extbase’s SignalSlot and TYPO3 custom hook system for extending the core in accordance with our implementation requirements. TYPO3 10 LTS implemented PSR 14, which is the standardized way for dispatching events. Before getting into the details of how this event dispatcher is used in TYPO3, let us have a look into PSR-14.
Whenever a piece of code hits a hook or signal, the third-party extension can register some sort of listener and alter, enhance, add to or simply observe (e.g. log) what happened. There were many approaches for implementing this in our code, that is for extending the core feature. So what happens is, someone will use one way and the other one will use a different way. That means, there was not a standardized approach for this. So in order to solve this, a group of people known as PHP Framework Interop Group (PHP-FIG) took up the task and came up with the standardized method “PHP Standard Recommendation 14 “which is called Event Dispatcher. For a more detailed introduction to PSR-14, there is a talk “PSR-14: A major PHP Event“ by Larry Garfield at the Dutch PHP Conference 2019”.
With PSR-14, it is possible to extend the core in a clean way without hacking the core, which would override the changes with the update of TYPO3. PSR-14 consists of four components:
An EventDispatcher is used to trigger an event. It executes registered listeners in the caller’s code. TYPO3 has a custom EventDispatcher implementation for now, however, all EventDispatchers of all frameworks are implementing Psr\EventDispatcher\EventDispatcherInterface. The EventDispatcher’s main method dispatch() is called in TYPO3 Core or extensions, which receives a PHP object and is then handed to all available listeners.
A ListenerProvider object contains all listeners for determining which event should be called for a given event. TYPO3 has a custom ListenerProvider.
Events are objects which act as the unit of communication between an Emitter and appropriate Listeners. By default, all registered listeners get triggered by an Event, however, if an Event has the interface Psr\EventDispatcher\StoppableEventInterface implemented, a listener can stop further execution of other event listeners.
Extensions and PHP packages can add listeners that are registered via YAML. They are usually associated with Event objects by the fully qualified name of the event to be listened to. It is the task of the ListenerProvider to provide configuration mechanisms to represent this relationship.
The listeners have to be registered in the file Configuration/Services.yaml with the tag event.listener. Let us see an example for listener registration.
Line 1: The registration happens in the Services section. This is where all the Dependency Injection configuration goes as well.
Line 2: The Fully Qualified Class Name (FQCN) of the listener.
Line 3: The registration of listeners is done with service tags (official Symfony documentation).
Line 4: The tag name for listener registration is event.listener. This tag will be recognized and processed by the aforementioned ListenerProviderPass.
Line 5: The identifier of the listener. This is used to order the listener before or after other listeners. If no identifier is specified the FQCN is the identifier.
Line 6: The method that should receive the Event. This is optional. If no attribute method is given, the class is treated as Invokable, thus __invoke method is called.
Line 7: The FQCN of the Event the listener is registered for.
Line 8: Optional listeners that need to run after our listener. We register before those. Similarly, we can have optional listeners that need to run before our listener. We register after those.
A list of the ordered Event listeners has also been added to the configuration module of the system extension low-level. Moreover, the list of all core PSR-14 events has been mentioned in List of Core PSR-14 [https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Hooks/Events/Index.html].
Now let us see an example of implementing event listeners into our extension. We can also refer to the talk of Benni Mack at the TYPO3 Developer Days 2019, “Don’t get hooked, listen to events! PSR-14 within TYPO3 v10 @ TYPO3 Developer Days 2019”
In version 10 of the mailer, the dispatcher dispatches and creates a new event and this event decides what we have to do with it.
Next we have to register the listener in the Configuration/Services.yaml file of our extension.
An example listener, which hooks into the Mailer API to modify Mailer settings to not send any emails, could look like this:
TYPO3 10 LTS still supports Signals and Hooks. By TYPO3 version 11 this will be deprecated. So it is better to update your code so that in the future it will save time when you upgrade your current version. There are some documentations available that we can refer to;
So start using events in your code for a better experience. Thank you for reading.