Just use Composer:
composer require semperton/events
Events requires PHP 7.4+
Listeners are added with an event class or interface name, a listener callback and an optional priority value (default is 0, negative values allowed). The listener callback can be any PHP callable and should accept only one argument - the event object.
use Semperton\Events\ListenerProvider;
interface EventInterface{}
final class TestEvent implements EventInterface
{
public $message = '';
}
$provider = new ListenerProvider();
$provider->addListener(TestEvent::class, function (TestEvent $event) {
$event->message .= ' World';
});
$provider->addListener(EventInterface::class, function (EventInterface $event) {
$event->message = 'Hello';
}, -1); // gets called first, because of higher priority (negatives allowed)
If you register a listener with an interface name, that listener will also be triggered if the dispatched event implements said interface.
Remove listeners with the removeListener()
method. Event name, listener and priority must match.
$myListener = function (TestEvent $event) {};
$provider->addListener(TestEvent::class, $myListener, 7);
$provider->removeListener(TestEvent::class, $myListener, 7); // priority must match too
All you need is a ListenerProvider
(collection of event listeners) and an EventDispatcher
.
use Semperton\Events\EventDispatcher;
// using the previously created ListenerProvider
$dispatcher = new EventDispatcher($provider);
$event = new TestEvent();
/** @var TestEvent */
$dispatchedEvent = $dispatcher->dispatch($event);
$dispatchedEvent === $event; // true
$dispatchedEvent->message; // 'Hello World'
If you want to call service methods in response to events, you may use a callable
to resolve your services, etc. For this purpose a DelegateListener
can be helpful:
$resolver = static function (string $class): object {
return new $class();
};
$listener = new DelegateListener($resolver, Service::class, 'method');
Or use the get
function of a PSR-11 Container as a resolver:
// $container is a Psr\Container\ContainerInterface
$listener = new DelegateListener([$container, 'get'], Service::class, 'method');
$provider->addListener(TestEvent::class, $listener);