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.
Parameter | Type | Required? | Description |
---|---|---|---|
$dispatcher | EventDispatcherInterface | Yes | A 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.
Parameter | Type | Required? | Description |
---|---|---|---|
$event | string | Yes | The event name to listen for (e.g. 'user.registered' ). |
$listener | callable | Yes | The 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.
Parameter | Type | Required? | Description |
---|---|---|---|
$event | string | Yes | The event name to listen for. |
$listener | callable | Yes | The 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.
Parameter | Type | Required? | Description |
---|---|---|---|
$event | string | Yes | The event name from which to remove the listener. |
$listener | callable | Yes | The 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.
Parameter | Type | Required? | Description |
---|---|---|---|
$event | string | Yes | The event name to fire (e.g. 'user.updated' ). |
...$args | mixed | No | Arguments 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.
Parameter | Type | Required? | Description |
---|---|---|---|
$event | string | Yes | The 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.