Event Listeners
Event Listeners react to domain events published by command handlers. They enable loose coupling between bounded contexts and handle side effects.
Listener Structure
Listeners implement ListenerInterface and use the __invoke pattern:
final readonly class BookEventHandler implements ListenerInterface
{
public function __invoke(DomainEventInterface $event): void
{
$this->logger->info('Book event occurred', [
'bookId' => $event->getBook()->getId()->getValue(),
]);
}
}
Event Registration
Listeners are registered in config/events.php:
return [
BookCreatedEvent::class => [
BookEventHandler::class,
],
LoanCreatedEvent::class => [
LoanCreatedEventHandler::class,
NotifyLibrarianHandler::class, // Multiple listeners allowed
],
];
Cross-Aggregate Communication
Listeners enable communication between bounded contexts:
final readonly class LoanCreatedEventHandler implements ListenerInterface
{
public function __invoke(DomainEventInterface $event): void
{
$command = new UpdateBookStatusCommand(
$event->getLoan()->getBookId(),
BookStatus::Borrowed
);
$this->commandBus->dispatch($command);
}
}
Best Practices
Do:
- React with side effects (logging, notifications)
- Keep listeners focused on single responsibilities
- Handle failures gracefully without breaking the flow
Don't:
- Contain complex business logic
- Create circular event chains
- Perform long-running operations synchronously
See Also
- Domain Events - What listeners react to
- Event-Driven Architecture - Conceptual foundation
- Event Bus - Event dispatching mechanism
- Command Bus - Listeners can dispatch commands