A domain event defines something important that happens in your domain model. These are domain specific events encapsulated as a simple data transfer object similar to the Command Design Pattern.
Events in this project are raised in the Entities or Service layer. Below is an example of the PasswordChangedEvent being raised in the Entity layer, and dispatched in the Service layer. This event is raised in the User Entity setPassword() method. The User Service releases and dispatches events when the update method is called.
public function setPassword($password)
{
$this->passwordHash = password_hash((string) $password, PASSWORD_BCRYPT);
if ($this->id !== null) {
$this->raise(
new PasswordChangedEvent(
$this->id,
$this->email,
$this->getFullName()
)
);
}
}
public function changePassword(int $userId, string $password)
{
$user = $this->userRepository->findOneById($userId);
$user->setPassword($password);
$this->update($user);
}
public function update(User & $user)
{
$this->throwValidationErrors($user);
$this->userRepository->update($user);
$this->eventDispatcher->dispatch($user->releaseEvents());
}
$eventDispatcher = new EventDispatcher;
$eventDispatcher->addSubscriber(new EmailSubscriber));
$serviceFactory = new ServiceFactory($eventDispatcher);
$userService = $serviceFactory->getUserService();
$userService->changePassword(1, 'password123');
class EmailSubscriber implements EventSubscriberInterface
{
public function getSubscribedEvents()
{
return [
PasswordChangedEvent::class => 'onPasswordChanged',
];
}
public function onPasswordChanged(PasswordChangedEvent $event)
{
$message = 'Dear ' . $event->getFullName() . "\n" .
'Per your request, we have successfully changed your password.';
$this->sendEmail('Revision to Your Account', $event->getEmail(), $message);
}
}