Inane\Event\Event
Base event class. Extend this to create custom events.
Inane\Event\StoppableEvent
Extends Event and implements StoppableEventInterface. Allows event propagation to be halted mid-dispatch; once stopped, propagation cannot be resumed.
propagationStopped:bool-
Whether propagation has been stopped. Once set to
trueit cannot be reset tofalse.
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.
Inane\Event\EventDispatcher
Implements EventDispatcherInterface. Dispatches events to all registered listeners via a ListenerProviderInterface. Respects StoppableEventInterface — propagation halts as soon as isPropagationStopped() returns true.
__construct(ListenerProviderInterface $provider)-
Accepts any listener provider implementing
ListenerProviderInterface.
Inane\Event\Provider\ListenerProvider
Basic listener provider. Listeners are registered per event class name and returned in the order they were added.
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.
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.
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.
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.
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.
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"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 firesLimited 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.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());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
// SecondPrioritised 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
// LowRandomised 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());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 listenerSimple 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'));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());