Skip to content

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