PHPackages                             horde/eventdispatcher - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. horde/eventdispatcher

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

horde/eventdispatcher
=====================

A simple PSR-14 EventDispatcher / ListenerProvider system for Horde

v1.0.0(1w ago)02.8k↑453.3%16BSD-3-ClausePHPPHP ^8

Since Nov 25Pushed 1w ago4 watchersCompare

[ Source](https://github.com/horde/EventDispatcher)[ Packagist](https://packagist.org/packages/horde/eventdispatcher)[ Docs](https://www.horde.org)[ RSS](/packages/horde-eventdispatcher/feed)WikiDiscussions FRAMEWORK\_6\_0 Synced 2d ago

READMEChangelog (4)Dependencies (18)Versions (9)Used By (6)

EventDispatcher
===============

[](#eventdispatcher)

[![Unit Tests](https://github.com/horde/eventdispatcher/actions/workflows/ci.yml/badge.svg)](https://github.com/horde/eventdispatcher/actions/workflows/ci.yml/badge.svg)

A simple PSR-14 EventDispatcher / ListenerProvider system for Horde

This library contains a simple PSR-14 EventDispatcher and one simple ListenerProvider using functionality from fig/eventdispatcher-util. It is similar in purpose to horde/pubsub but shares no code.

Features
--------

[](#features)

- **PSR-14 compliant** - Full implementation of PSR-14 Event Dispatcher
- **StoppableEventInterface support** - Events can halt propagation mid-chain
- **PSR-3 logging integration** - Optional debug logging of event dispatch
- **Type-safe listener matching** - Automatic filtering based on event type hints
- **Multiple callable types** - Closures, invokable objects, array callables, static methods

Installation
------------

[](#installation)

```
composer require horde/eventdispatcher
```

Basic Usage
-----------

[](#basic-usage)

```
use Horde\EventDispatcher\EventDispatcher;
use Horde\EventDispatcher\SimpleListenerProvider;

// Create a listener provider and add listeners
$provider = new SimpleListenerProvider();
$provider->addListener(function (MyEvent $event): void {
    // Handle the event
    $event->process();
});

// Create dispatcher
$dispatcher = new EventDispatcher($provider);

// Dispatch events
$event = new MyEvent();
$result = $dispatcher->dispatch($event);
```

Exception Handling
------------------

[](#exception-handling)

**Important:** Exceptions thrown by listeners propagate directly to the caller of `dispatch()`.

The EventDispatcher does **not** catch or suppress exceptions from listeners. If a listener throws an exception:

1. The exception propagates immediately to the `dispatch()` caller
2. Subsequent listeners in the chain **are not executed**
3. Event modifications made before the exception **are preserved**
4. The partially-processed event object remains in its modified state

It is the job of the listener to

- harden against expected problems
- catch expected exceptions
- emit logs or CouldNotHandle events
- track any relevant markers in the event object

if that is appropriate for the handler, event type and circumstances. Otherwise the originator of the event must handle or whatever is in layers beyond it.

### Example

[](#example)

```
$provider = new SimpleListenerProvider();

$provider->addListener(function (MyEvent $event): void {
    $event->step1Complete = true; // This runs
});

$provider->addListener(function (MyEvent $event): void {
    throw new RuntimeException('Processing failed'); // Exception thrown here
});

$provider->addListener(function (MyEvent $event): void {
    $event->step3Complete = true; // This NEVER runs
});

$dispatcher = new EventDispatcher($provider);

try {
    $event = new MyEvent();
    $dispatcher->dispatch($event);
} catch (RuntimeException $e) {
    // Handle the exception
    // $event->step1Complete is true (modifications preserved)
    // $event->step3Complete is undefined (listener never ran)
}
```

### Best Practices

[](#best-practices)

**For application code:**

- Wrap `dispatch()` calls in try-catch blocks if listener failures should be handled gracefully
- Consider using a wrapper dispatcher that catches and logs exceptions if you need resilient event handling
- Use StoppableEventInterface for controlled propagation stopping (doesn't throw)

**For listener code:**

- Only throw exceptions for truly exceptional conditions
- Consider catching and logging errors within the listener if the event chain should continue
- Document any exceptions your listener may throw

StoppableEventInterface
-----------------------

[](#stoppableeventinterface)

Events implementing `StoppableEventInterface` can halt propagation:

```
use Psr\EventDispatcher\StoppableEventInterface;

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

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

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

// In a listener
$listener = function (MyStoppableEvent $event): void {
    if ($event->shouldStop()) {
        $event->stopPropagation(); // Remaining listeners won't be called
    }
};
```

Logging
-------

[](#logging)

Pass a PSR-3 logger to enable debug logging:

```
use Psr\Log\Logger;

$logger = new Logger();
$dispatcher = new EventDispatcher($provider, $logger);

// Logs each listener execution at DEBUG level
$dispatcher->dispatch($event);
```

License
-------

[](#license)

BSD-3-Clause

###  Health Score

52

—

FairBetter than 96% of packages

Maintenance98

Actively maintained with recent releases

Popularity24

Limited adoption so far

Community25

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~335 days

Recently: every ~105 days

Total

6

Last Release

7d ago

PHP version history (2 changes)v1.0.0alpha1PHP ^7.4 || ^8

v1.0.0alpha2PHP ^8

### Community

Maintainers

![](https://www.gravatar.com/avatar/c931cd02664859360478593450d6c473a05bb12b209dfacfc534cd13257cc7ef?d=identicon)[ralflang](/maintainers/ralflang)

![](https://www.gravatar.com/avatar/e4f6c6771993db2ed500959b42353f6cf6a2ca0406d9617f7ae680f4504faa4a?d=identicon)[horde](/maintainers/horde)

![](https://www.gravatar.com/avatar/816e2b926f25f8cd2939054c7a7173011b4303d690e25ab61bf33cf8c7cf71ae?d=identicon)[tdannhauer](/maintainers/tdannhauer)

---

Top Contributors

[![ralflang](https://avatars.githubusercontent.com/u/646976?v=4)](https://github.com/ralflang "ralflang (31 commits)")[![TDannhauer](https://avatars.githubusercontent.com/u/6716033?v=4)](https://github.com/TDannhauer "TDannhauer (1 commits)")

---

Tags

eventspsr-14event dispatcher

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/horde-eventdispatcher/health.svg)

```
[![Health](https://phpackages.com/badges/horde-eventdispatcher/health.svg)](https://phpackages.com/packages/horde-eventdispatcher)
```

###  Alternatives

[crell/tukio

A robust, stand-alone PSR-14 event dispatcher implementation.

114214.2k17](/packages/crell-tukio)[fig/event-dispatcher-util

Useful utility classes and traits for implementing the PSR events standard

27473.2k21](/packages/fig-event-dispatcher-util)[phly/phly-event-dispatcher

Experimental event dispatcher for PSR-14

26284.5k6](/packages/phly-phly-event-dispatcher)[horde/horde

Horde base application

583.0k71](/packages/horde-horde)[horde/kronolith

Calendar and scheduling application

101.5k5](/packages/horde-kronolith)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
