Event Dispatcher
An efficient PSR-14 event dispatcher.
Installation
To get started, install the event-dispatcher repository via the Composer package manager:
composer require zaphyr-org/event-dispatcher
Basic usage
Events enable your code to respond to specific occurrences or actions within your application, promoting modularity and flexibility by allowing different components to react independently to the same event.
In the following example, we will create a UserEvent class that will be dispatched each time a user logs in to your
application. We will then create a listener that will be called each time the UserEvent is dispatched:
class UserEvent
{
public function isLoggedIn(): bool
{
return true;
}
}
$listenerProvider = new Zaphyr\EventDispatcher\ListenerProvider();
$listenerProvider->addListener(UserEvent::class, function (UserEvent $event) {
if ($event->isLoggedIn()) {
// …
}
});
$eventDispatcher = new Zaphyr\EventDispatcher\EventDispatcher($listenerProvider);
$eventDispatcher->dispatch(new UserEvent());
In the above example we have created a new Zaphyr\EventDispatcher\ListenerProvider instance and added a listener to
the addListener method. The addListener method accepts two arguments: the event name and a callable. The callable
will be called each time the event is dispatched. We then created a new Zaphyr\EventDispatcher\EventDispatcher instance
and passed the ListenerProvider instance to the constructor. Finally, we dispatched our example event by calling
the dispatch method on the EventDispatcher instance. We will now take a closer look at the ListenerProvider and
EventDispatcher classes.
Subscribe to events
The Zaphyr\EventDispatcher\ListenerProvider class is responsible for subscribing to events and registering listeners
for these events. The ListenerProvider class implements the Psr\EventDispatcher\ListenerProviderInterface:
$listenerProvider = new Zaphyr\EventDispatcher\ListenerProvider();
Add listeners
The addListener method allows you to add a listener to a specific event. This method accepts two arguments: the event
name and a callable. The event name must be the fully qualified class name of the event object. The callable will be
called each time the event is dispatched. The callable must accept one argument: the event object. The callable can be
any PHP callable, including a closure or an invokable object:
$listenerProvider->addListener($eventName, $listenerCallable);
In the following example, we created a UserListener class with the __invoke method. The __invoke method will be
called each time the UserEvent is dispatched:
class UserListener
{
public function __invoke(UserEvent $event)
{
if ($event->isLoggedIn()) {
// …
}
}
}
$listenerProvider->addListener(UserEvent::class, new UserListener());
The addListener method is not part of the PSR-14 Psr\EventDispatcher\ListenerProviderInterface.
Prioritize listeners
The addListener method allows to influence the caller order of the event listeners by providing a priority. The higher
the priority number of a listener is, the earlier the listener is called:
$listenerProvider->addListener($eventName, $listenerCallable2, -100);
$listenerProvider->addListener($eventName, $listenerCallable1, 100);
If listeners have the same priority, they are called in the order they were added:
$listenerProvider->addListener($eventName, $listenerCallable1, 100);
$listenerProvider->addListener($eventName, $listenerCallable2, 100);
The Zaphyr\EventDispatcher\ListenerProvider exposes a set of constants that can be used to prioritize listeners:
Zaphyr\EventDispatcher\ListenerProvider::PRIORITY_LOW(-100)Zaphyr\EventDispatcher\ListenerProvider::PRIORITY_NORMAL(0)Zaphyr\EventDispatcher\ListenerProvider::PRIORITY_HIGH(100)
$listenerProvider->addListener(
$eventName,
$listenerCallable,
Zaphyr\EventDispatcher\ListenerProvider::PRIORITY_HIGH
);
Dispatch events
The Zaphyr\EventDispatcher\EventDispatcher class is the central point of the event dispatcher repository. It is
responsible for dispatching events to all subscribed listeners. The EventDispatcher class implements the
Psr\EventDispatcher\EventDispatcherInterface. After you have created all your desired listeners, you can create a new
EventDispatcher instance and pass the ListenerProvider instance to the constructor:
$eventDispatcher = new Zaphyr\EventDispatcher\EventDispatcher($listenerProvider);
Now that you have created a new EventDispatcher instance, you can dispatch events by calling the dispatch method on
the EventDispatcher instance. The dispatch method accepts one argument: the event object.
$eventDispatcher->dispatch($eventObject);
Stop event propagation
Sometimes you may want to stop the propagation of an event to other listeners. The event-dispatcher repository provides
a Zaphyr\EventDispatcher\AbstractStoppableEvent class that you can extend to create stoppable events. The
AbstractStoppableEvent class implements the Psr\EventDispatcher\StoppableEventInterface:
class StoppableEvent extends Zaphyr\EventDispatcher\AbstractStoppableEvent
{
// …
}
The AbstractStoppableEvent class provides a stopPropagation method that you can call to stop the propagation of the
event to other listeners:
$listenerProvider->addListener(StoppableEvent::class, function (StoppableEvent $event) {
$event->stopPropagation();
});