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

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

memran/marwa-event
==================

Lightweight PSR-14 event dispatcher for PHP 8.2+ with stable priority ordering, stoppable events, and optional container-aware resolution.

v0.2.0(1mo ago)0831MITPHPPHP &gt;=8.2CI passing

Since Aug 12Pushed 1mo agoCompare

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

READMEChangelogDependencies (9)Versions (3)Used By (1)

Marwa Event
===========

[](#marwa-event)

[![CI](https://github.com/memran/marwa-event/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/memran/marwa-event/actions/workflows/ci.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/1da8d515b6e2f94777bf48fad64903b9c2586c68692ff305e787eb9ccd0bc3d5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d656d72616e2f6d617277612d6576656e742e737667)](https://packagist.org/packages/memran/marwa-event)[![Total Downloads](https://camo.githubusercontent.com/46a36e854931a0457902af86e691719b76b0fe52e4e0ed9b451a77914213d4b9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d656d72616e2f6d617277612d6576656e742e737667)](https://packagist.org/packages/memran/marwa-event)[![PHP 8.2+](https://camo.githubusercontent.com/ccaa43fc634d348cffccb1d8db7b55d9f17c5d46944bc99a15c3c982724b387d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/ccaa43fc634d348cffccb1d8db7b55d9f17c5d46944bc99a15c3c982724b387d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)[![PHPStan 2.x](https://camo.githubusercontent.com/fa7d884e709724ce03a59cc92cc27dbcb383be15d7e32a0c29f2cdec762e46e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d322e782d324533343430)](https://camo.githubusercontent.com/fa7d884e709724ce03a59cc92cc27dbcb383be15d7e32a0c29f2cdec762e46e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d322e782d324533343430)[![PHPUnit 10](https://camo.githubusercontent.com/f0a104d2fbaec248f0b4145ded1d76e86c9d02eb85b5a3b2667722df70ff5bdf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850556e69742d31302d334339434437)](https://camo.githubusercontent.com/f0a104d2fbaec248f0b4145ded1d76e86c9d02eb85b5a3b2667722df70ff5bdf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850556e69742d31302d334339434437)[![Infection Ready](https://camo.githubusercontent.com/2942fd0ba7d4f406d20e42e24563701ecb5a9d36cb4a358f21c59895a3d2b783/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f496e66656374696f6e2d72656164792d364534304339)](https://camo.githubusercontent.com/2942fd0ba7d4f406d20e42e24563701ecb5a9d36cb4a358f21c59895a3d2b783/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f496e66656374696f6e2d72656164792d364534304339)[![License MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)

Lightweight PSR-14 event dispatching for PHP 8.2+ with predictable synchronous delivery, stable priority ordering, optional PSR-11 container integration, and a small framework-agnostic API.

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

[](#requirements)

- PHP `>=8.2`
- Composer

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

[](#installation)

```
composer require memran/marwa-event
```

For local development:

```
composer install
composer ci
```

Features
--------

[](#features)

- PSR-14 aligned dispatcher and listener provider
- Stable priority ordering, including ties and mixed parent/interface listeners
- Flexible listener definitions: callable, `"Class@method"`, `["Class", "method"]`, and invokable class strings
- Optional PSR-11 container resolution for listeners and subscriber class strings
- Stoppable events via `Marwa\Event\Contracts\StoppableEvent`
- Fail-fast validation for invalid listener and subscriber definitions
- PHPUnit, PHPStan 2.x, PHP-CS-Fixer, GitHub Actions CI, and Infection setup

Quick Start
-----------

[](#quick-start)

```
use Marwa\Event\Bus\EventBus;
use Marwa\Event\Core\EventDispatcher;
use Marwa\Event\Core\ListenerProvider;
use Marwa\Event\Resolver\ListenerResolver;

$resolver = new ListenerResolver();
$provider = new ListenerProvider($resolver);
$dispatcher = new EventDispatcher($provider);
$bus = new EventBus($provider, $dispatcher);

$bus->listen(UserRegistered::class, SendWelcomeMail::class, 100);
$bus->listen(UserRegistered::class, [AuditListener::class, 'handle'], 50);
$bus->listen(UserRegistered::class, static function (UserRegistered $event): void {
    // metrics or notifications
}, 10);

$bus->dispatch(new UserRegistered('user@example.com'));
```

Examples
--------

[](#examples)

### Define a Stoppable Event

[](#define-a-stoppable-event)

```
use Marwa\Event\Contracts\StoppableEvent;

final class UserRegistered extends StoppableEvent
{
    public function __construct(public string $email) {}
}
```

### Register a Subscriber

[](#register-a-subscriber)

```
use Marwa\Event\Contracts\Subscriber;

final class UserSubscriber implements Subscriber
{
    public static function getSubscribedEvents(): array
    {
        return [
            UserRegistered::class => [
                ['sendWelcome', 100],
                ['audit', 50],
            ],
        ];
    }

    public function sendWelcome(UserRegistered $event): void {}

    public function audit(UserRegistered $event): void {}
}

$bus->subscribe(new UserSubscriber());
```

### Remove a Listener

[](#remove-a-listener)

```
$listenerId = $bus->listen(UserRegistered::class, SendWelcomeMail::class, 100);

$bus->forget($listenerId);
```

### Listen on an Interface or Parent Event Type

[](#listen-on-an-interface-or-parent-event-type)

```
interface DomainEvent {}

class BaseOrderEvent implements DomainEvent {}

final class OrderPlaced extends BaseOrderEvent {}

$bus->listen(DomainEvent::class, LogDomainEvent::class, 100);
$bus->listen(BaseOrderEvent::class, UpdateReadModel::class, 50);
$bus->listen(OrderPlaced::class, SendOrderEmail::class, 10);

$bus->dispatch(new OrderPlaced());
```

### Use Container-Aware Resolution

[](#use-container-aware-resolution)

```
use Marwa\Event\Bus\EventBus;
use Marwa\Event\Core\EventDispatcher;
use Marwa\Event\Core\ListenerProvider;
use Marwa\Event\Resolver\ListenerResolver;

$resolver = new ListenerResolver($container);
$provider = new ListenerProvider($resolver);
$dispatcher = new EventDispatcher($provider);
$bus = new EventBus($provider, $dispatcher, $container);

$bus->listen(UserRegistered::class, SendWelcomeMail::class);
$bus->subscribe(UserSubscriber::class);
```

When a PSR-11 container is provided, listener and subscriber class strings are resolved from the container first.

### Swallow Listener Exceptions Explicitly

[](#swallow-listener-exceptions-explicitly)

```
$dispatcher = new EventDispatcher($provider, swallowExceptions: true);
$bus = new EventBus($provider, $dispatcher);
```

The default remains `false`, which is usually the safer production choice.

Project Layout
--------------

[](#project-layout)

```
src/
  Bus/         Facade-style API
  Contracts/   Shared interfaces and base event types
  Core/        Dispatcher and listener provider
  Resolver/    Listener notation resolution
tests/         PHPUnit test suite
example.php    Minimal runnable example

```

Development Workflow
--------------------

[](#development-workflow)

```
composer test          # PHPUnit
composer test:coverage # Coverage output; requires Xdebug or PCOV
composer analyse       # PHPStan 2.x
composer mutate        # Infection mutation testing; requires Xdebug, PCOV, or phpdbg
composer lint          # PHP-CS-Fixer dry run
composer fix           # PHP-CS-Fixer apply fixes
composer ci            # test + analyse + lint
```

Notes
-----

[](#notes)

- Higher priority values run first.
- Equal priorities keep registration order.
- Invalid listeners and subscribers throw `InvalidArgumentException`.
- Exceptions bubble by default unless `EventDispatcher` is explicitly configured otherwise.

Quality and Release
-------------------

[](#quality-and-release)

The repository includes PHPUnit 10, PHPStan 2.x, PHP-CS-Fixer, GitHub Actions CI, and Infection configuration. Run `composer ci` before opening a PR or cutting a release.

Mutation testing is available through Infection. Run `composer mutate` after `composer test` when you want to measure how well the suite detects behavioral regressions. It requires Xdebug, PCOV, or `phpdbg` so Infection can collect coverage for the initial test pass.

Contributing
------------

[](#contributing)

See [AGENTS.md](AGENTS.md) for repository-specific contributor guidance.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance90

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity40

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

Every ~230 days

Total

2

Last Release

48d ago

PHP version history (2 changes)v0.1.0PHP &gt;=8.1

v0.2.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/8cf906a31a250a940314fe42f8a18f449647bfe18095457350ff0081cf8dd3c2?d=identicon)[memran](/maintainers/memran)

---

Top Contributors

[![memran](https://avatars.githubusercontent.com/u/7415198?v=4)](https://github.com/memran "memran (5 commits)")

---

Tags

eventspsr-14listenerdispatcher

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[psr/event-dispatcher

Standard interfaces for event handling.

2.3k618.8M865](/packages/psr-event-dispatcher)[crell/tukio

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

112183.8k13](/packages/crell-tukio)[fig/event-dispatcher-util

Useful utility classes and traits for implementing the PSR events standard

27423.2k19](/packages/fig-event-dispatcher-util)[jbzoo/event

Library for event-based development

29760.0k5](/packages/jbzoo-event)[phly/phly-event-dispatcher

Experimental event dispatcher for PSR-14

26209.9k4](/packages/phly-phly-event-dispatcher)

PHPackages © 2026

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