Skip to content

Domain Events

Domain Events represent significant facts that have occurred in the domain. They enable loose coupling between bounded contexts.

Characteristics

  • Immutable: Events are readonly facts
  • Past tense naming: BookCreatedEvent, not CreateBookEvent
  • Self-contained: Include all data needed to react
  • Published after action: Dispatched after successful persistence

Creating Events

Extend DomainEventAbstract:

final readonly class BookCreatedEvent extends DomainEventAbstract
{
    public function __construct(
        private DateTimeImmutable $occurredOn,
        private Book $book
    ) {}

    public function getAggregateId(): IdInterface
    {
        return $this->book->getId();
    }

    public function getBook(): Book
    {
        return $this->book;
    }
}

Publishing Events

Events are published from command handlers after persistence:

public function handle(CommandInterface $command): void
{
    $book = new Book(/* ... */);
    $this->bookRepository->save($book);

    $this->eventBus->dispatch(new BookCreatedEvent(
        occurredOn: $this->clock->now(),
        book: $book,
    ));
}

Naming Conventions

Action Event Name
Create book BookCreatedEvent
Update book BookUpdatedEvent
Borrow book LoanCreatedEvent
Return book LoanReturnedEvent

Event Registration

Configure listeners in config/events.php:

return [
    BookCreatedEvent::class => [BookEventHandler::class],
    LoanCreatedEvent::class => [
        LoanCreatedEventHandler::class,
        NotifyLibrarianHandler::class,
    ],
];

Best Practices

  • Use past tense naming
  • Always include occurredOn timestamp
  • Include all data needed to react
  • Dispatch after successful persistence
  • Keep listeners simple

See Also