inanepain / event
PSR-14 implementation: event dispatcher.
Requires
- psr/event-dispatcher: ^1.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-08 13:57:13 UTC
README
Table of Contents
inanepain/event
PSR-14 implementation: event dispatcher.
Install
composercomposer require inanepain/event
1. Events
1.1. Event
Inane\Event\Event
Base event class. Extend this to create custom events.
1.1.1. Properties
name:string-
The event name. Defaults to the fully qualified class name of the event if not explicitly set.
1.2. Stoppable Event
Inane\Event\StoppableEvent
Extends Event and implements StoppableEventInterface. Allows event propagation to be halted mid-dispatch; once stopped, propagation cannot be resumed.
1.2.1. Properties
propagationStopped:bool-
Whether propagation has been stopped. Once set to
trueit cannot be reset tofalse.
1.2.2. Methods
isPropagationStopped():bool-
Returns
trueif propagation has been stopped. stopPropagation():void-
Stops propagation of the event to further listeners.
1.3. Limited Event
Inane\Event\LimitedEvent
Extends StoppableEvent to halt propagation after the event has been offered to
a fixed number of listeners. The listener limit defaults to 1; a limit of
0 prevents all listeners from being invoked. Calling the inherited
stopPropagation() method stops propagation sooner.
1.3.1. Properties
limit:int-
The readonly maximum number of listeners that may handle the event.
1.3.2. Methods
isPropagationStopped():bool-
Returns
trueonce the listener limit is exhausted or propagation has been stopped manually. Each check increments the internal listener count, so letEventDispatcherperform the checks during dispatch.
2. Dispatcher
2.1. Event Dispatcher
Inane\Event\EventDispatcher
Implements EventDispatcherInterface. Dispatches events to all registered listeners via a ListenerProviderInterface. Respects StoppableEventInterface — propagation halts as soon as isPropagationStopped() returns true.
2.1.1. Constructor
__construct(ListenerProviderInterface $provider)-
Accepts any listener provider implementing
ListenerProviderInterface.
2.1.2. Methods
dispatch(object $event):object-
Dispatches the event to all applicable listeners and returns the (possibly modified) event.
3. Listener Providers
3.1. Default Provider
Inane\Event\Provider\ListenerProvider
Basic listener provider. Listeners are registered per event class name and returned in the order they were added.
3.1.1. Methods
addListener(string|object $event, callable $listener):static-
Registers a listener for the given event class name or instance. Returns the provider for chaining.
addAttributedListener(object $listener):static-
Registers every public method annotated with
Inane\Event\Attribute\Listeneron the supplied listener object. Repeated attributes register a method for each declared event; priority metadata does not affect insertion order. getListenersForEvent(object $event):iterable-
Returns all listeners registered for the event’s class, in insertion order.
3.2. Prioritised Provider
Inane\Event\Provider\PrioritisedListenerProvider
Listener provider that dispatches listeners in priority order. Higher priority values are called first; listeners with equal priority are called in insertion order.
3.2.1. Methods
addListener(string|object $event, callable $listener, int $priority = 0):static-
Registers a listener with an optional priority (default
0). Returns the provider for chaining. addAttributedListener(object $listener):static-
Registers every public method annotated with
Inane\Event\Attribute\Listeneron the supplied listener object, using each attribute’s priority. getListenersForEvent(object $event):iterable-
Returns listeners ordered by descending priority.
clearListeners(string|object $event):void-
Removes all listeners registered for the given event.
3.3. Randomised Provider
Inane\Event\Provider\RandomisedListenerProvider
Extends ListenerProvider. Returns listeners in a randomised order on each dispatch. Useful for testing that application behaviour does not depend on listener execution order.
3.3.1. Methods
Inherits addListener() from ListenerProvider.
getListenersForEvent(object $event):iterable-
Returns all listeners for the event in a randomised order.
3.4. Aggregate Provider
Inane\Event\Provider\AggregateProvider
Combines multiple listener providers into one. Each sub-provider is queried in the order it was added; all listeners from the first provider are returned before any from the second, and so on. Per-provider internal ordering is preserved, but cross-provider ordering is not guaranteed.
3.4.1. Methods
addProvider(ListenerProviderInterface $provider):static-
Appends a provider to the aggregate. Returns the aggregate for chaining.
getListenersForEvent(object $event):iterable-
Yields listeners from each sub-provider in registration order.
3.5. Listener Attribute
Use #[Listener] on a public method to register it as a listener for an event
class. The event argument must name an existing class; priority is optional
and defaults to 0.
4. Examples
4.1. Event
4.1.1. Basic Event
Basic Event Example
use Inane\Event\Event; // Use directly $event = new Event(); echo $event->name; // "Inane\Event\Event" // Extend to create a named domain event class UserRegistered extends Event { public function __construct( public readonly string $username ) {} } $event = new UserRegistered('alice'); echo $event->name; // "UserRegistered" echo $event->username; // "alice"
4.1.2. Stoppable Event
Stoppable Event Example
use Inane\Event\StoppableEvent; use Inane\Event\EventDispatcher; use Inane\Event\Provider\ListenerProvider; class Odd extends StoppableEvent { public function __construct( public readonly string $message = '' ) {} } $provider = new ListenerProvider(); $dispatcher = new EventDispatcher($provider); $provider->addListener(Odd::class, function (Odd $event) { echo "Listener 1: " . $event->message . "\n"; if ($event->message > 5) $event->stopPropagation(); }); $provider->addListener(Odd::class, function (Odd $event) { echo "Listener 2: " . $event->message . "\n"; }); $dispatcher->dispatch(new Odd('3')); // both listeners fire $dispatcher->dispatch(new Odd('7')); // only listener 1 fires
4.1.3. Limited Event
Limited Event Example
<?php declare(strict_types=1); use Inane\Event\EventDispatcher; use Inane\Event\LimitedEvent; use Inane\Event\Provider\ListenerProvider; $handledBy = []; $provider = new ListenerProvider(); $provider->addListener(LimitedEvent::class, function (LimitedEvent $event) use (&$handledBy): void { $handledBy[] = 'first listener'; }); $provider->addListener(LimitedEvent::class, function (LimitedEvent $event) use (&$handledBy): void { $handledBy[] = 'second listener'; }); $provider->addListener(LimitedEvent::class, function (LimitedEvent $event) use (&$handledBy): void { $handledBy[] = 'third listener'; }); $dispatcher = new EventDispatcher($provider); $dispatcher->dispatch(new LimitedEvent(limit: 2)); // $handledBy contains the first and second listeners only.
4.2. Dispatcher
4.2.1. Event Dispatcher
Event Dispatcher Example
use Inane\Event\Event; use Inane\Event\EventDispatcher; use Inane\Event\Provider\ListenerProvider; $provider = new ListenerProvider(); $dispatcher = new EventDispatcher($provider); $provider->addListener(Event::class, function (Event $event) { echo "Received: " . $event->name . "\n"; }); $dispatcher->dispatch(new Event());
4.3. Listener Providers
4.3.1. Default Provider
Default Provider Example
use Inane\Event\Event; use Inane\Event\EventDispatcher; use Inane\Event\Provider\ListenerProvider; $provider = new ListenerProvider(); $dispatcher = new EventDispatcher($provider); $provider->addListener(Event::class, fn (Event $e) => print("First\n")) ->addListener(Event::class, fn (Event $e) => print("Second\n")); $dispatcher->dispatch(new Event()); // First // Second
4.3.2. Prioritised Provider
Prioritised Provider Example
use Inane\Event\Event; use Inane\Event\EventDispatcher; use Inane\Event\Provider\PrioritisedListenerProvider; $provider = new PrioritisedListenerProvider(); $dispatcher = new EventDispatcher($provider); $provider->addListener(Event::class, fn (Event $e) => print("Low\n"), priority: -10) ->addListener(Event::class, fn (Event $e) => print("Default\n")) ->addListener(Event::class, fn (Event $e) => print("High\n"), priority: 10); $dispatcher->dispatch(new Event()); // High // Default // Low
4.3.3. Randomised Provider
Randomised Provider Example
use Inane\Event\Event; use Inane\Event\EventDispatcher; use Inane\Event\Provider\RandomisedListenerProvider; $provider = new RandomisedListenerProvider(); $dispatcher = new EventDispatcher($provider); $provider->addListener(Event::class, fn (Event $e) => print("A\n")) ->addListener(Event::class, fn (Event $e) => print("B\n")) ->addListener(Event::class, fn (Event $e) => print("C\n")); // Order of A, B, C is random on each dispatch $dispatcher->dispatch(new Event());
4.3.4. Aggregate Provider
Aggregate Provider Example
use Inane\Event\Event; use Inane\Event\EventDispatcher; use Inane\Event\Provider\AggregateProvider; use Inane\Event\Provider\ListenerProvider; use Inane\Event\Provider\PrioritisedListenerProvider; $basic = new ListenerProvider(); $prioritized = new PrioritisedListenerProvider(); $basic->addListener(Event::class, fn (Event $e) => print("Basic listener\n")); $prioritized->addListener(Event::class, fn (Event $e) => print("Priority listener\n"), priority: 5); $aggregate = new AggregateProvider(); $aggregate->addProvider($basic) ->addProvider($prioritized); $dispatcher = new EventDispatcher($aggregate); $dispatcher->dispatch(new Event()); // Basic listener // Priority listener
4.3.5. Simple example
Simple Listener Attribute Example
<?php declare(strict_types=1); use Inane\Event\Attribute\Listener; use Inane\Event\EventDispatcher; use Inane\Event\Provider\ListenerProvider; final readonly class UserRegisteredEvent { public function __construct( public string $email, ) {} } final class SendWelcomeEmail { #[Listener(UserRegisteredEvent::class)] public function send(UserRegisteredEvent $event): void { // Send a welcome email to $event->email. } } $provider = new ListenerProvider(); $provider->addAttributedListener(new SendWelcomeEmail()); $dispatcher = new EventDispatcher($provider); $dispatcher->dispatch(new UserRegisteredEvent('user@example.com'));
4.3.6. Comprehensive example
Listener is repeatable, so one public method can listen for more than one
event class. Use PrioritisedListenerProvider when priority matters: higher
numeric priorities run first, while listeners with the same priority retain
their registration order. ListenerProvider intentionally ignores declared
attribute priorities and always retains registration order.
Comprehensive Listener Attribute Example
<?php declare(strict_types=1); use Inane\Event\Attribute\Listener; use Inane\Event\EventDispatcher; use Inane\Event\Provider\PrioritisedListenerProvider; final readonly class InvoicePaidEvent {} final readonly class AccountSuspendedEvent {} final class AuditAndNotificationListener { #[Listener(event: InvoicePaidEvent::class, priority: 10)] #[Listener(event: AccountSuspendedEvent::class, priority: 10)] public function writeAuditLog(InvoicePaidEvent|AccountSuspendedEvent $event): void { // Write the received event to the audit log. } #[Listener(event: InvoicePaidEvent::class, priority: 100)] public function notifyFinance(InvoicePaidEvent $event): void { // Notify finance before the audit log is written. } } $provider = new PrioritisedListenerProvider(); $provider->addAttributedListener(new AuditAndNotificationListener()); $dispatcher = new EventDispatcher($provider); $dispatcher->dispatch(new InvoicePaidEvent());