solophp/event-dispatcher

Minimal, PSR-14 compatible event dispatcher with priorities and stoppable propagation.

Installs: 9

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/solophp/event-dispatcher

v1.1.0 2025-12-26 20:56 UTC

This package is auto-updated.

Last update: 2025-12-26 20:58:08 UTC


README

Latest Version on Packagist License PHP Version Code Coverage

Minimal, PSR-14 compatible event dispatcher with priorities and stoppable propagation.

Requirements

  • PHP 8.3+

Installation

composer require solophp/event-dispatcher

Usage

Adding Listeners Directly

use Solo\EventDispatcher\{EventDispatcher, ListenerProvider};

$provider = new ListenerProvider();

$provider->addListener(
    UserRegistered::class,
    fn (UserRegistered $e) => print "Welcome, {$e->username}!\n",
    priority: 10
);

$dispatcher = new EventDispatcher($provider);
$dispatcher->dispatch(new UserRegistered('john'));

Using Subscribers

use Solo\EventDispatcher\EventSubscriberInterface;

final class WelcomeEmailSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            UserRegistered::class => ['onUserRegistered', 10],
        ];
    }

    public function onUserRegistered(UserRegistered $event): void
    {
        echo "Welcome, {$event->username}!" . PHP_EOL;
    }
}

$provider = new ListenerProvider();
$provider->addSubscriber(new WelcomeEmailSubscriber());

$dispatcher = new EventDispatcher($provider);
$dispatcher->dispatch(new UserRegistered('john'));

Subscriber Configuration Formats

return [
    EventClass::class => 'methodName',
    EventClass::class => ['methodName', 10],                         // with priority
    EventClass::class => [['firstMethod', 20], ['secondMethod', 0]], // multiple handlers
];

Using the Factory

use Solo\EventDispatcher\EventDispatcherFactory;

$dispatcher = EventDispatcherFactory::create(
    listeners: [
        UserRegistered::class => fn (UserRegistered $e) => print "Welcome!\n",
    ],
    subscribers: [
        new WelcomeEmailSubscriber(),
        WelcomeEmailSubscriber::class,           // or class-string
        fn () => new WelcomeEmailSubscriber(),   // or factory callable
    ],
);

Stoppable Events

use Solo\EventDispatcher\AbstractStoppableEvent;

final class OrderPlaced extends AbstractStoppableEvent
{
    public function __construct(public int $orderId) {}
}

$provider->addListener(OrderPlaced::class, function (OrderPlaced $e) {
    if ($e->orderId < 0) {
        $e->stopPropagation(); // subsequent listeners won't be called
    }
}, priority: 100);

$provider->addListener(OrderPlaced::class, function (OrderPlaced $e) {
    // this won't run if propagation was stopped
});

Checking for Listeners

// checks for listeners including parent classes and interfaces
if ($provider->hasListenersFor(UserRegistered::class)) {
    $dispatcher->dispatch(new UserRegistered('john'));
}

Testing

composer test        # cs-check + analyze + phpunit
composer cs-check    # PHPCS (PSR-12)
composer cs-fix      # PHPCBF auto-fix
composer analyze     # PHPStan (level 8)

License

MIT