Event Dispatcher and Event Handler
Events
Whenever any discussion related to “events” comes in PHP, I usually lean to think, “There is not a real event in PHP”, “PHP works on the synchronization of execution”. Therefore, it will not use events. There are some frameworks that provide the functionality of “Event Dispatcher” like Symfony. Here I am taking one example of Symfony to explain “Event Dispatcher”.
The Symfony Event Dispatcher component implements the Mediator pattern in a simple and effective way to make all these things possible and to make your projects truly extensible.
I am taking an example of HttpKernel component. After response object creation, that object can use to modify in the system’s other element. (E.g., add some cache headers). Symfony Kernel throws an event (kernel.response) to do a particular action. Here, I will explain how it works:
- A listener (PHP object) tells a central dispatcher object that it wants to listen to the kernel.response event;
- Now Symfony kernel asks dispatcher object to dispatch the kernel.response event, passing with it an Event object to the Response object;
- The dispatcher calls a method to all listeners of the kernel.response event, and allows all to make modifications to the Response object.
When an event is dispatched, it is identified by a unique name (e.g. kernel.response), which any number of listeners might be listening to. An Event instance is created and pass to all listeners. Event object itself often contains data about the event, which is being dispatched.
When the dispatcher notifies listeners, it passes an actual Event object to those listeners. The base Event class contains a method for stopping event propagation. Data about a specific event needs to pass with the Event object so listeners have the information, which requires. A special subclass that has additional methods for retrieving and overriding information can be passed when dispatching an event. For example, the kernel.response event uses a FilterResponseEvent, which contains methods to get and even replace the Response object.
The Dispatcher
The dispatcher is the central object of the event dispatcher system. A single dispatcher is created, which maintains a registry of listeners. When an event is dispatched through the dispatcher, it notifies all listeners registered with that event:
Connecting Listeners
Here you need to connect a listener via dispatcher so when the event is dispatched, it will notify. A call to the dispatcher’s addListener() method associates any valid PHP callable to an event:
The addListener() method takes up to three arguments:
- The event name (string) that this listener wants to listen to;
- A PHP callable that will be executed when the specified event is dispatched;
- An optional priority integer that determines when a listener is triggered versus other listeners (defaults to 0). If two listeners have the same priority, they are executed in the order that they were added to the dispatcher.
A PHP callable is a PHP variable that can be used by the call_user_func() function and returns true when passed to the is_callable() function.
Once a listener is registered with the dispatcher, it waits until the event is notified.
Stopping Event Flow/Propagation
In some cases, it may make sense for a listener to prevent any other listeners from being called. In other words, the listener needs to be able to tell the dispatcher to stop all propagation of the event to future listeners (i.e. to not notify any more listeners). This can be accomplished from inside a listener via the stopPropagation() method:
IsPropagationStopped() method is used to detect if an event was stopped or not. This method returns a boolean value.
Dispatcher Shortcuts
You can also use a plain Event object if you do not want custom event Object. You do not even need to pass this to the dispatcher, as it will create one by default:
The event dispatcher always returns event object, which was dispatched, i.e. either the event that was passed or the event that was created internally by the dispatcher.
Other Dispatchers
Besides the commonly used EventDispatcher, the component also has some other dispatchers:
- The Container Aware Event Dispatcher
- The Immutable Event Dispatcher
- The Traceable Event Dispatcher