Skip to main content

Event System

Overview

DomainFlow Core includes a flexible event system that allows you to dispatch custom events and listen for them. This helps decouple different parts of your application and makes it straightforward to implement “reactive” features without tightly coupling modules.


Key Concepts

  • Event Dispatcher: A central mechanism that keeps track of listeners and calls them when specific events happen.
  • Listeners: Functions or methods registered to respond whenever a particular event is fired.
  • Wildcard Matching: You can use wildcard patterns like user.* to listen for multiple events sharing a common prefix.
  • Error Handling: If an error occurs while firing an event, an error event is dispatched, giving you a chance to respond.

Method Descriptions

Below are the primary methods on your Application instance for working with events. By default, the application sets up a basic event dispatcher for you, but you can swap in a custom one at any time.

setEventDispatcher($dispatcher)

Signature

public function setEventDispatcher(EventDispatcherInterface $dispatcher): void

Purpose
Allows you to replace the default event dispatcher with your own, as long as it implements the same interface.

ParameterTypeRequired?Description
$dispatcherEventDispatcherInterfaceYesA custom or built-in dispatcher implementing the required methods.

Usage Example

$app->setEventDispatcher(new MyCustomDispatcher());

on($event, $listener)

Signature

public function on(string $event, callable $listener): void

Purpose
Registers a listener that gets called every time the specified event is dispatched.

ParameterTypeRequired?Description
$eventstringYesThe event name to listen for (e.g. 'user.registered').
$listenercallableYesThe callback executed when the event is fired.

Usage Example

$app->on('user.registered', function ($user) {
// Send welcome email, etc.
});

once($event, $listener)

Signature

public function once(string $event, callable $listener): void

Purpose
Similar to on(), but the listener is automatically unregistered after it handles its first event.

ParameterTypeRequired?Description
$eventstringYesThe event name to listen for.
$listenercallableYesThe callback executed once when the event is fired.

Usage Example

$app->once('session.expiring', function () {
// This will run only once
});

off($event, $listener)

Signature

public function off(string $event, callable $listener): void

Purpose
Unregisters a previously attached listener for the given event, preventing it from receiving further notifications.

ParameterTypeRequired?Description
$eventstringYesThe event name from which to remove the listener.
$listenercallableYesThe specific callback to detach.

Usage Example

$app->off('user.registered', $welcomeListener);

fireEvent($event, ...$args)

Signature

public function fireEvent(string $event, mixed ...$args): void

Purpose
Dispatches an event and optionally passes any arguments to its registered listeners.

ParameterTypeRequired?Description
$eventstringYesThe event name to fire (e.g. 'user.updated').
...$argsmixedNoArguments passed to listener callbacks.

Usage Example

$app->fireEvent('user.registered', $newUser);
  • If an error occurs in a listener, the system dispatches an error event. You can catch that to handle or log the exception.

hasListeners($event)

Signature

public function hasListeners(string $event): bool

Purpose
Checks if there are any registered listeners (including wildcard listeners) for a given event name.

ParameterTypeRequired?Description
$eventstringYesThe event name to check (e.g. 'order.*').

Usage Example

if ($app->hasListeners('order.shipped')) {
// Possibly optimize if we know shipping triggers heavy logic
}

Comparative Descriptions

  • on() vs. once()
  • on() attaches a listener permanently until explicitly removed.
  • once() automatically removes itself after a single execution.
  • fireEvent() vs. off()
  • fireEvent() triggers all matching listeners.
  • off() stops a specific listener from receiving future events, so it won’t be triggered next time.

Practical Examples

// Set a listener that triggers every time a user registers
$app->on('user.registered', function ($user) {
// Save activity log, send welcome email, etc.
});

// Set a one-time listener for a session expiration event
$app->once('session.expiring', function () {
// Maybe show a special one-time warning banner
});

// Fire an event when a user successfully registers
$app->fireEvent('user.registered', $newUser);

// Check if any listeners exist for a specific event
if ($app->hasListeners('user.registered')) {
// Possibly do additional preparations
}

Extensibility

  • Custom Dispatchers: Use setEventDispatcher() to swap out the default logic for your own, maybe a more sophisticated dispatcher that queues events or logs them.
  • Wildcard Patterns: You can register a listener to handle a pattern like user.*, capturing all user-related events.
  • Module-Based Events: Larger apps might define event names with domain-based prefixes—e.g., inventory.product.created—so you can systematically manage them.

This event system gives you a clean, decoupled way to communicate across different parts of your application. It can be as simple or as advanced as you need.