A lightweight PHP Event Dispatcher that follows PSR-14, with optional helpers and facade for ergonomic usage.
- This is an open-source library, and contributions are welcome.
- If you have any suggestions, bug reports, or feature requests, please open an issue or submit a pull request on the project repository.
- PHP version 8.4 or newer is required
- composer
composer require naingaunglwin-dev/event-dispatcher- PSR-14 compliant core dispatcher
- Stoppable events (
stopPropagation()) - One-time listeners (
once()) - Payload support with
GenericEvent - User-friendly
Support\Eventhelper - Static
Facade\EventAPI for Laravel-style usage - Lightweight and easy to extend
This package provides a PSR-14 compliant core and optional helpers.
- Core (PSR-14)
EventDispatcherListenerProviderStoppableEvent
- Extras (Framework-friendly)
GenericEvent(string-based events with payload)Support\EventhelperFacade\Event(Laravel-style static API)
You may use only the core, or opt into the helpers.
Use GenericEvent when you want string-based events with a mutable payload.
- Example
use Naingaunglwin\EventDispatcher\EventDispatcher;
use Naingaunglwin\EventDispatcher\ListenerProvider;
use Naingaunglwin\EventDispatcher\GenericEvent;
$provider = new ListenerProvider();
$dispatcher = new EventDispatcher($provider);
$provider->addListener('init', function (GenericEvent $event) {
$event->setPayload('foo', 'bar');
});
$provider->addListener('init', function (GenericEvent $event) {
echo $event->getPayload('foo') . PHP_EOL;
});
$dispatcher->dispatch(new GenericEvent('init'));- GenericEvent allows non-class-based events
- Payload is mutable and shared across listeners
- Fully compatible with stoppable propagation
Class-based events are the preferred PSR-14 approach.
- Define an Event
use Naingaunglwin\EventDispatcher\StoppableEvent;
class UserRegistered extends StoppableEvent
{
public function __construct(
public readonly string $username
) {}
}- Register Listeners
$provider->addListener(UserRegistered::class, function (UserRegistered $event) {
echo "User registered: {$event->username}" . PHP_EOL;
});- Dispatch the Event
$dispatcher->dispatch(new UserRegistered('john'));Listeners may be invokable classes
- Listener Class
class SendWelcomeEmail
{
public function __invoke(UserRegistered $event): void
{
echo "Sending welcome email to {$event->username}" . PHP_EOL;
}
}Register the Listener
$provider->addListener(UserRegistered::class, new SendWelcomeEmail());Listeners can stop further propagation.
- Example
$provider->addListener(UserRegistered::class, function (UserRegistered $event) {
if ($event->username === 'admin') {
$event->stopPropagation();
}
});
$provider->addListener(UserRegistered::class, function () {
echo "This will not run if propagation is stopped";
});One-time listeners are removed automatically after execution.
$provider->addOnceListener('init', function () {
echo "This runs only once" . PHP_EOL;
});The Support\Event helper wraps the core dispatcher for convenience.
- Example
use Naingaunglwin\EventDispatcher\Support\Event;
use Naingaunglwin\EventDispatcher\GenericEvent;
$event = new Event();
$event->on('init', function (GenericEvent $event) {
$event->setPayload('foo', 'bar');
});
$event->once('init', function () {
echo "Run once" . PHP_EOL;
});
$event->on('init', function (GenericEvent $event) {
echo $event->getPayload('foo') . PHP_EOL;
});
$event->dispatch(new GenericEvent('init'));
$event->dispatch(new GenericEvent('init'));- Simplifies listener registration
- Manages provider and dispatcher internally
- Still uses PSR-14 compliant core internally
For maximum ergonomics, use the facade.
Example
use Naingaunglwin\EventDispatcher\Support\Facade\Event;
use Naingaunglwin\EventDispatcher\GenericEvent;
Event::on('init', function (GenericEvent $event) {
$event->setPayload('foo', 'bar');
});
Event::once('init', function () {
echo "Just once" . PHP_EOL;
});
Event::on('init', function (GenericEvent $event) {
echo $event->getPayload('foo') . PHP_EOL;
});
Event::dispatch('init');
Event::dispatch('init');Resetting the Facade
- Useful for tests or long-running processes:
Event::reset();