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, notCreateBookEvent - 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
occurredOntimestamp - Include all data needed to react
- Dispatch after successful persistence
- Keep listeners simple
See Also
- Event-Driven Architecture - Conceptual foundation
- Event Bus - Event dispatching plugin
- Event Listeners - Reacting to events
- Clock - Generating occurredOn timestamps