Search by

stougeiro / event

stougeiro

Lightweight event dispatcher with wildcard pattern matching and automatic deduplication. Dispatch string-based events, register invokable listeners, and load configurations from PHP files — all with zero cache overhead.

Package info

github.com/stougeiro/event

pkg:composer/stougeiro/event

Fund package maintenance!

Buymeacoffee

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-10 23:21 UTC

This package is auto-updated.

Last update: 2026-09-14 17:22:51 UTC


README

PHP PHPStan-Level Pest-php License

Event

Lightweight event dispatcher with wildcard pattern matching and automatic deduplication. Dispatch string-based events, register invokable listeners, and load configurations from PHP files — all with zero cache overhead.

✨ Features

  • String-based event dispatching
    Events are simple strings, no classes or enums required.

  • Wildcard pattern matching
    Register listeners on post.* to catch all post.created, post.updated, etc.

  • Automatic deduplication
    Same listener instance on post.created and post.* executes only once per dispatch.

  • File-based listener loading
    Load listener mappings from PHP config files for clean bootstrapping.

  • High performance
    Native merge by class name, no cache layers, no auxiliary structures.

  • Framework-agnostic
    Works with any PHP 8.2+ project.

  • Global helpers
    event() and events() for quick dispatch without instantiation.

📦 Installation

composer require stougeiro/event

📐 Event Name Rules

Event names must follow a strict pattern for consistency and fast regex matching.

Structure

segment.separated.by.dots

Segments: alphanumeric characters only (a-z, A-Z, 0-9)
Separators: ., :, or -
Wildcard: * allowed alone or at the end

Valid Names

Name Description
* Global wildcard (all events)
post.created Standard dot notation
user:registered Colon separator
order-item.placed Hyphen separator
app.module.event Multiple segments
post.* Wildcard at end
user:* Wildcard with colon

Invalid Names

Name Reason
post created Space not allowed
.post.created Cannot start with separator
post.created. Cannot end with separator
post..created Double separator
post.*.detail Wildcard not at end

🚀 Usage

Two paths: instance or global helper.

Path 1: Instance

use STDW\Event\EventManager;

$em = new EventManager();

$em->listen('order.created', new SendEmailListener());
$em->dispatch('order.created', ['id' => 42]);

Path 2: Global helpers

events()->listen('order.created', new SendEmailListener());
event('order.created', ['id' => 42]);
Function Returns Use
events() EventManager Register listeners, load config
event($name, $data) void Dispatch shorthand
// Register
events()->listen('user.*', new AuditListener());

// Or load from file
events()->load(__DIR__ . '/events.php');

// Dispatch
event('user.created', ['action' => 'created']);

Both share the same EventManager instance — listeners registered via events() are triggered by event().

Wildcard listeners

events()->listen('user.*', new AuditListener());

event('user.created', ['action' => 'created']);
event('user.deleted', ['action' => 'deleted']);
// Both trigger the same listener

Deduplication: same listener, multiple events

$logger = new LoggingListener();

events()->listen('post.created', $logger);
events()->listen('post.*', $logger);

event('post.created', ['title' => 'Hello']);
// LoggingListener executes ONCE, not twice

Load from file

// events.php
return [
    '*'               => [GlobalAuditListener::class],
    'order.created'   => [SendEmailListener::class],
    'order.paid'      => [UpdateInventoryListener::class],
    'order.*'         => [OrderListener::class],
];

// bootstrap
events()->load(__DIR__ . '/events.php');
event('order.created', ['id' => 42]);
// GlobalAuditListener: ✅ (via *)
// SendEmailListener: ✅ (exact)
// OrderListener: ✅ (via order.*)

Global wildcard: listen to all events

events()->listen('*', new AuditListener());

event('post.created', ['id' => 1]);
event('user.deleted', ['id' => 2]);
// AuditListener triggered for both

🧠 Why?

Event systems don't need to be complex. This library provides a dispatcher that combines string-based events, wildcard matching, and automatic deduplication — without cache layers, queues, or heavy abstractions.

By using class names as merge keys, duplicate listeners are eliminated naturally at registration and resolution time. The result is a predictable, high-performance dispatcher that works in any PHP 8.2+ environment.

🤝 Contributions

Contributions are welcome. Feel free to open issues or submit pull requests.