Search by

sugiphp / events

tzappa

PSR-14 Event Dispatcher

Package info

github.com/SugiPHP/Events

pkg:composer/sugiphp/events

Statistics

Installs: 672

Dependents: 2

Suggesters: 0

Stars: 3

Open Issues: 0

1.0.0 2014-12-16 13:21 UTC

This package is auto-updated.

Last update: 2026-09-15 07:56:04 UTC


README

A minimal, dependency-light PSR-14 event dispatcher for PHP 8.3+.

It provides:

  • Dispatcher — a PSR-14 EventDispatcherInterface implementation that calls listeners in registration order and stops on StoppableEventInterface.
  • ListenerProvider — a PSR-14 ListenerProviderInterface implementation that maps an event class (or any of its parent classes / interfaces) to the listeners registered for it.
  • EventDispatcherTrait — an optional trait to add dispatching capability to any class without requiring a hard dependency on Dispatcher in its constructor.

Installation

composer require sugiphp/events ^2.0

Basic usage

use SugiPHP\Events\Dispatcher;
use SugiPHP\Events\ListenerProvider;

$provider = new ListenerProvider();
$provider->addListener(UserRegistered::class, function (UserRegistered $event) {
    // send a welcome email, etc.
});

$dispatcher = new Dispatcher($provider);

$event = new UserRegistered($user);
$dispatcher->dispatch($event);

Any PHP object can be used as an event — there is no base Event class or interface to extend.

Registering listeners

ListenerProvider::addListener() takes an event class (or interface) name and any PHP callable:

$provider->addListener(UserRegistered::class, new SendWelcomeEmail());
$provider->addListener(UserRegistered::class, [$logger, 'logRegistration']);
$provider->addListener(UserRegistered::class, 'notify_admins');

Listeners are invoked in the order they were registered. Registering against a parent class or an interface matches every event that instanceof that type:

interface DomainEvent {}
class UserRegistered implements DomainEvent {}

// Fires for UserRegistered and any other DomainEvent implementation.
$provider->addListener(DomainEvent::class, $auditLogger);

Stopping propagation

Events that implement Psr\EventDispatcher\StoppableEventInterface can stop remaining listeners from being called:

use Psr\EventDispatcher\StoppableEventInterface;

class UserRegistered implements StoppableEventInterface
{
    private bool $stopped = false;

    public function isPropagationStopped(): bool
    {
        return $this->stopped;
    }

    public function stopPropagation(): void
    {
        $this->stopped = true;
    }
}

Once a listener calls stopPropagation(), Dispatcher::dispatch() stops calling any further listeners and returns the event as-is.

Using the trait

EventDispatcherTrait lets a class expose a dispatch() method without requiring a Dispatcher to be injected through its constructor. If no dispatcher has been set, dispatch() is a no-op that returns the event unchanged.

use SugiPHP\Events\Dispatcher;
use SugiPHP\Events\EventDispatcherTrait;
use Psr\EventDispatcher\EventDispatcherInterface;

class UserService implements EventDispatcherInterface
{
    use EventDispatcherTrait;
}

$service = new UserService();
$service->setEventDispatcher(new Dispatcher($provider));
$service->dispatch(new UserRegistered($user));

Requirements

Testing

composer test

License

MIT