Last active
January 26, 2019 09:54
-
-
Save latik/ab647c92a63ebe4664c3ef67b1705237 to your computer and use it in GitHub Desktop.
CQRS +- ES notes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| // Aggregate method (domain logic) | |
| // Domain event | |
| // Command | |
| // Command Handler | |
| // Projector | |
| // Listener | |
| // There are 4 places validation takes place in CQRS system. | |
| // Client side(js) | |
| // Server side(controller) | |
| // Application service(CommandHandler) | |
| // Domain Objects(AggrigateRoot) | |
| class UserRegisterRequest | |
| { | |
| public function toArray(): array | |
| { | |
| } | |
| } | |
| class UserController | |
| { | |
| public function register(UserRegisterRequest $request) | |
| { | |
| // do some validation here | |
| // use value object for do validation(required field, valid email, etc.) | |
| $params = $request->toArray(); | |
| $this->commandBus->dispatch(UserRegisterCommand::fromArray($params)); | |
| // The DTO containing the intent and data to execute the command. | |
| } | |
| } | |
| class UserRegisterCommand | |
| { | |
| public function fromArray(array $params): self | |
| { | |
| // store $params as context | |
| } | |
| } | |
| //--------------------------- | |
| // CommandBus | |
| //--------------------------- | |
| /** A command handler will be registered with the command bus and handle the commands that are dispatched. | |
| * The command handler can be seen as a small layer between your application code and the actual domain code. | |
| * | |
| * In the end a command handler listens for commands and translates commands to | |
| * method calls on the actual aggregate roots. | |
| **/ | |
| class UserRegisterCommandHandler | |
| { | |
| public function handle(UserRegisterCommand $command): void // UserRegisterCommandHandler is CommandHandler | |
| { | |
| try { | |
| // do some validation here | |
| $user = User::register($command); // <-- call AggregateRoot method | |
| $this->userRepository->save($user); // Skip this step in ES case. | |
| // Instead need use projectors for ReadModel change | |
| $this->eventBus->dispatch($user->realeseEvents()); | |
| //$this->eventBus->dispatch($user->getRecordedEvents()); | |
| } catch (\DomainException $exception) { | |
| $this->eventBus->dispatch(new UserUnableRegisterEvent($user, $exception)); | |
| } | |
| } | |
| } | |
| class User | |
| { | |
| public function register(UserRegisterCommand $command) | |
| { | |
| // do some domain validation here | |
| $user = new static(); | |
| $user->email = $command->email; | |
| ///.. | |
| $user->raise(new UserRegisteredEvent($user)); // UserWasCreatedEvent is DomainEvent | |
| //$user->recordThat(new UserRegisteredEvent($user)); | |
| return $user; | |
| } | |
| } | |
| //--------------------------- | |
| // EventBus //All events MUST be stored into EventStorage (use transactions, it's most critical part of the ES app) | |
| //--------------------------- | |
| // UpdateExistedUsersFromNewRegistration is one of many others projectors for event UserWasCreatedEvent | |
| // it store user data into DB for use in ReadModels at future | |
| //UserProjector@onRegistered(UserRegisteredEvent $event): void OR | |
| class UpdateExistedUsersListFromNewRegistration | |
| { | |
| public function handle(UserRegisteredEvent $event): void | |
| { | |
| $this->dbConnection->insert('users', [ | |
| 'id' => $event->user->id, | |
| // .... | |
| ]); | |
| } | |
| } | |
| // UserWasCreatedEmail is one of many others listeners for event UserWasCreatedEvent | |
| // It's describe feature, example: send email to new user | |
| // Also it may fire new Command!! | |
| class SendWelcomeMailWhenUserSigned | |
| { | |
| public function handle(UserRegisteredEvent $event): void | |
| { | |
| $this->mailer->send( | |
| $event->user->email | |
| ); | |
| } | |
| } | |
| //https://pilsniak.com/cqrs-es-php-prooph/ | |
| //https://github.com/nepda/iwsf | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment