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();
});