Skip to content
Muhammet Şafak edited this page May 25, 2026 · 2 revisions

FAQ

Short answers to common questions. The longer-form material lives in the linked reference pages.

What's the difference between Events and EventEmitter?

Events is a static facade over a single shared Event instance; EventEmitter is the instantiable, dependency-injectable sibling.

Events facade EventEmitter
Registry one global, shared one per instance
on() returns the shared Event (chainable) $this (chainable)
once() available
Stops chain on false return
Arguments varargs array
Simulate / debug mode
Removal API (off / removeAllListeners)
Reset between tests/jobs Events::reset() new instance

See Events facade vs EventEmitter for the full comparison.

Which one should I use?

  • Use Events when you want WordPress-style global hooks, ergonomic varargs at the call site, and the optional simulate / debug instrumentation.
  • Use EventEmitter when you want a plain object you can build per-request, dependency-inject, or hand to a service — without reaching for global state.

once(), off(), and removeAllListeners() exist on both APIs, so they are not a reason to pick one over the other.

You can use both side-by-side — they do not share state.

Do priorities actually re-order listeners?

Yes. Listeners with a lower numeric priority fire first; within the same priority bucket, registration order (FIFO) wins. The named constants are aliases for integers:

  • PRIORITY_HIGH = 10 — runs first
  • PRIORITY_NORMAL = 100 — default
  • PRIORITY_LOW = 200 — runs last
Events::on('e', fn() => print("late\n"),  Events::PRIORITY_LOW);
Events::on('e', fn() => print("first\n"), Events::PRIORITY_HIGH);
Events::trigger('e');
// → first
// → late

1.x had a bug that silently ignored $priority and dispatched in registration order. That is fixed in 2.0 — see Listeners & Priorities and the Migration Guide.

Are event names case-sensitive?

No. Both APIs lowercase the event name before storing or looking it up, so 'User.Registered', 'user.registered', and 'USER.REGISTERED' reference the same event. Choose one convention and stick with it.

How do I pass multiple arguments?

// Events facade — varargs
Events::trigger('order.placed', $order, 'web', 2);

// EventEmitter — array
$bus->emit('order.placed', [$order, 'web', 2]);

Listeners always receive the arguments unpacked positionally:

function (array $order, string $source, int $version) { /* … */ }

How do I stop the chain?

Return strict false from a listener attached via the Events facade; trigger() will return false and skip the remaining listeners. EventEmitter::emit() does not short-circuit on false — see Stopping Propagation for the patterns that work there.

Can a listener mutate the event payload?

Yes — pass the payload by reference if it is an array or object, and mutate it in place:

Events::on('user.before_save', function (array &$user) {
    $user['email'] = strtolower($user['email']);
});

$user = ['email' => 'JANE@example.com'];
Events::trigger('user.before_save', $user);

echo $user['email']; // jane@example.com

Objects are passed by handle in PHP — mutations propagate without any ampersand.

Can the same callable be registered twice?

Yes. It will fire twice. Re-registering does not deduplicate. EventEmitter::removeListener() removes all instances of that callable in one call.

Does this package implement a PSR?

No. The codebase predates and does not target PSR-14 (Event Dispatcher). If you need PSR-14 specifically, build a thin adapter over EventEmitter (a listener provider + dispatcher pair is ~30 lines).

Is it thread-safe?

PHP's standard model has no shared-memory threads in user code, so "thread-safe" is not meaningful here. The library is not safe to use from multiple parallel coroutines that share an Event/EventEmitter instance unless your runtime serialises access.

What PHP versions are supported?

The 2.x line targets PHP 5.6+, and the runtime contract is verified in CI (PHP 5.6 / 7.0 / 7.1 / 7.2 are linted to make sure the source parses; PHP 7.3 / 7.4 / 8.0 / 8.1 / 8.2 / 8.3 / 8.4 run the full PHPUnit suite). The 1.x line was tied to PHP 7.x; the README in the legacy initphp/event-emitter repo claimed 5.4+.

Is this still maintained?

Yes — initphp/events is the active package. The split initphp/event-emitter repository is deprecated; its contents now ship inside this package. See Migration Guide.

Where do I report a bug?

github.com/InitPHP/Events/issues. Include a minimal reproduction, your PHP version, and the package version (composer show initphp/events).

Where do I ask a usage question?

Use github.com/orgs/InitPHP/discussions. Bug reports go in Issues; design questions, "how do I do X", and broader conversation go in Discussions.

Is there a way to list all registered events?

Yes. On the low-level emitter directly, or on the facade via Events::getEmitter():

$bus->listeners();                                 // every listener across every event
$bus->listeners('user.login');                     // just that event

Events::getEmitter()->listeners('user.login');     // same, via the facade

The returned array is already merged across both the regular and one-shot registries and sorted in dispatch order (priority + FIFO).

See also

Clone this wiki locally