PHPackages                             componenta/event - 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. componenta/event

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

componenta/event
================

PSR-14 compliant event dispatcher with prioritized and composite listener providers

v1.0.0(1mo ago)00MITPHPPHP ^8.4

Since Jun 16Pushed 1mo agoCompare

[ Source](https://github.com/componenta/event)[ Packagist](https://packagist.org/packages/componenta/event)[ RSS](/packages/componenta-event/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

Componenta Event
================

[](#componenta-event)

[![PHP 8.4+](https://camo.githubusercontent.com/80c4564163cef31b2a66baaeb95a5bf4a418bcb5242a5ae707b94c2f4811e742/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e342532422d626c7565)](https://camo.githubusercontent.com/80c4564163cef31b2a66baaeb95a5bf4a418bcb5242a5ae707b94c2f4811e742/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e342532422d626c7565)[![License MIT](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)[![PSR-14](https://camo.githubusercontent.com/0a24ed972f674977e0a03eaf139d4ef2c5891c925dadf3f52e8d82a2e7ae10a7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d31342d696e666f726d6174696f6e616c)](https://camo.githubusercontent.com/0a24ed972f674977e0a03eaf139d4ef2c5891c925dadf3f52e8d82a2e7ae10a7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5053522d31342d696e666f726d6174696f6e616c)[![Tests](https://camo.githubusercontent.com/f65785e12b2986254242d44be11a9b2d51212871a2254231f4517d02ac256ffd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d36392532307061737365642d627269676874677265656e)](https://camo.githubusercontent.com/f65785e12b2986254242d44be11a9b2d51212871a2254231f4517d02ac256ffd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d36392532307061737365642d627269676874677265656e)

Minimal PSR-14 event dispatcher with prioritized and composite listener providers. Mutable providers with unsubscribe tokens, immutable dispatcher.

**[Русская документация](README.ru.md)**

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

[](#installation)

```
composer require componenta/event
```

Requirements
------------

[](#requirements)

- PHP 8.4+
- `psr/event-dispatcher` ^1.0

Related Packages
----------------

[](#related-packages)

PackageWhy it matters here`psr/event-dispatcher`Defines the PSR-14 dispatcher and listener-provider interfaces.`componenta/auth`Can publish authentication and session lifecycle events.`componenta/cqrs`Can publish command lifecycle events through `EventMiddleware`.`componenta/error-handler`Can report errors through listeners.`componenta/di`Can create listeners from the application container.Quick Start
-----------

[](#quick-start)

```
use Componenta\Event\EventDispatcher;
use Componenta\Event\Provider\ListenerProvider;

$provider = new ListenerProvider();
$provider->addListener(UserRegistered::class, fn(UserRegistered $e) => sendWelcomeEmail($e->user));

$dispatcher = new EventDispatcher($provider);
$dispatcher->dispatch(new UserRegistered($user));
```

Components
----------

[](#components)

### `EventDispatcher`

[](#eventdispatcher)

Final, readonly PSR-14 dispatcher. The provider reference is shared — listeners registered later are visible to all dispatches.

```
$dispatcher = new EventDispatcher($provider);
$event = $dispatcher->dispatch(new OrderPlaced(...));  // returns the event
$fork  = $dispatcher->withProvider($otherProvider);    // new instance
```

Events implementing `Psr\EventDispatcher\StoppableEventInterface` halt propagation when `isPropagationStopped()` becomes `true`. An already-stopped event skips all listeners.

### `ListenerProvider`

[](#listenerprovider)

Plain listener registry keyed by event class. `addListener()` returns an unsubscribe closure.

```
$provider = new ListenerProvider();

$off = $provider->addListener(PostPublished::class, $handler);
$off();  // removes the listener

$provider->removeListener(PostPublished::class, $handler);  // bool
$provider->has(PostPublished::class);                       // bool
$provider->contains(PostPublished::class, $handler);        // bool
```

### `PrioritizedProvider`

[](#prioritizedprovider)

Listeners are dispatched in priority order. Sorting is lazy and cache-aware — adding a listener after a dispatch invalidates the cached order.

```
use Componenta\Event\Provider\PrioritizedProvider;
use Componenta\Event\Provider\SortMode;

$provider = new PrioritizedProvider(mode: SortMode::DESC);   // default
$provider->addListener(CommentPosted::class, $auditHandler, priority: 100);
$provider->addListener(CommentPosted::class, $defaultHandler);  // 0 by default
```

Priorities are resolved in this order: explicit `$priority` argument → `PrioritizedListenerInterface::$priority` → `0`. Listeners with equal priority are dispatched in registration order (stable sort).

### `PrioritizedListenerInterface`

[](#prioritizedlistenerinterface)

Invokable listeners can expose their own priority:

```
use Componenta\Event\Provider\PrioritizedListenerInterface;

final class LogAuditEvent implements PrioritizedListenerInterface
{
    public int $priority { get => 1000; }

    public function __invoke(AuditEvent $event): void { /* ... */ }
}

$provider->addListener(AuditEvent::class, new LogAuditEvent());  // priority 1000 from interface
```

### `CompositeProvider`

[](#compositeprovider)

Aggregates multiple providers into one. `contains()` is recursive; `has()` works across `EventTypeAwareProviderInterface` children.

```
use Componenta\Event\Provider\CompositeProvider;

$composite = new CompositeProvider([$coreProvider, $moduleProvider]);
$composite->add($pluginProvider);

$dispatcher = new EventDispatcher($composite);
```

Bulk Registration
-----------------

[](#bulk-registration)

```
$provider->addListeners([
    PostPublished::class => [$sendDigest, $updateIndex],
    CommentPosted::class => $notifyAuthor,
]);

// Prioritized: [callable, int] pairs or bare callables within one group
$prio->addListeners([
    AuditEvent::class => [
        [$rotateLogs,  100],
        [$persistAudit, 50],
        $defaultLogger,        // priority 0 or from interface
    ],
]);
```

Patterns
--------

[](#patterns)

### One-shot listener

[](#one-shot-listener)

```
$off = null;
$off = $provider->addListener(Booted::class, function (Booted $e) use (&$off) {
    $off();         // unsubscribe before running (re-entrancy safe)
    initialize($e);
});
```

### Scoped subscription

[](#scoped-subscription)

```
function withTemporaryListener(ListenerProvider $p, string $event, callable $h, callable $block): mixed
{
    $off = $p->addListener($event, $h);
    try { return $block(); }
    finally { $off(); }
}
```

Reference
---------

[](#reference)

SymbolPurpose`EventDispatcher`PSR-14 dispatcher, final readonly`ListenerProvider`Plain keyed-by-event-class registry`PrioritizedProvider`Priority-ordered registry with lazy sort`CompositeProvider`Aggregate of child providers, recursive `contains``EventTypeAwareProviderInterface`Contract for providers that expose `has(eventType)``PrioritizedListenerInterface`Listener-side priority declaration`SortMode``ASC` / `DESC` for `PrioritizedProvider`All mutable providers expose: `addListener`, `addListeners`, `removeListener`, `contains`, `has`. `addListener` returns an unsubscribe `Closure`.

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance91

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

43d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20490712?v=4)[Andrey Shelamkoff](/maintainers/Shelamkoff)[@Shelamkoff](https://github.com/Shelamkoff)

---

Top Contributors

[![Shelamkoff](https://avatars.githubusercontent.com/u/20490712?v=4)](https://github.com/Shelamkoff "Shelamkoff (1 commits)")

---

Tags

eventpsr-14event dispatcherlistenerprioritized

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/componenta-event/health.svg)

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

###  Alternatives

[league/event

Event package

1.6k153.4M215](/packages/league-event)[phly/phly-event-dispatcher

Experimental event dispatcher for PSR-14

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

Event dispatcher package

106.1k2](/packages/slince-event-dispatcher)

PHPackages © 2026

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