The valid place to inject a projection service to handle domain objects or events
I'm trying to implement a simple CQRS+ES project to understand how it should work. The Prooph library is a way too complicated and has too many options.
As long as I understand I should have a CommandBus that will handle commands and execute domain logic. I've injected a Symfony's Messanger into a controller and it works. So, the aggregate root creates an event and apply it to a domain model. Then, the command handler has an injected repository that saves the domain (saves domain's events). But I can not get how should I update projection for this domain.
Here how a command handler looks like
class CreateBudgetHandler
{
private $budgetRepository;
public function __construct(
BudgetRepository $budgetRepository
) {
$this->budgetRepository = $budgetRepository;
}
public function __invoke(
CreateBudgetCommand $command
) {
$budget = Budget::create(
new BudgetId(Uuid::uuid4()),
new Amount($command->getBudget()->getAmount()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getStartDate()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getEndDate())
);
$this->budgetRepository->save($budget);
}
}
So, it simply gets a command, calls a named constructor for the domain model (Budget::create
) and passes it to a repository that will extract all recorded events and saves them into an event store database.
I'm wondering is it ok to inject another repository into the command handler that will save the domain model object into another table? Something like this
$this->budgetProject->insert($budget);
The insert
method will take a domain model, reads recorded events, transforms them into an INSERT/UPDATE/DELETE queries and runs them.
php symfony projection cqrs event-sourcing
add a comment |
I'm trying to implement a simple CQRS+ES project to understand how it should work. The Prooph library is a way too complicated and has too many options.
As long as I understand I should have a CommandBus that will handle commands and execute domain logic. I've injected a Symfony's Messanger into a controller and it works. So, the aggregate root creates an event and apply it to a domain model. Then, the command handler has an injected repository that saves the domain (saves domain's events). But I can not get how should I update projection for this domain.
Here how a command handler looks like
class CreateBudgetHandler
{
private $budgetRepository;
public function __construct(
BudgetRepository $budgetRepository
) {
$this->budgetRepository = $budgetRepository;
}
public function __invoke(
CreateBudgetCommand $command
) {
$budget = Budget::create(
new BudgetId(Uuid::uuid4()),
new Amount($command->getBudget()->getAmount()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getStartDate()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getEndDate())
);
$this->budgetRepository->save($budget);
}
}
So, it simply gets a command, calls a named constructor for the domain model (Budget::create
) and passes it to a repository that will extract all recorded events and saves them into an event store database.
I'm wondering is it ok to inject another repository into the command handler that will save the domain model object into another table? Something like this
$this->budgetProject->insert($budget);
The insert
method will take a domain model, reads recorded events, transforms them into an INSERT/UPDATE/DELETE queries and runs them.
php symfony projection cqrs event-sourcing
1
Protection should be listening to the event stream independently, as a separate service, or at least separate subroutine inside the command processing service.
– Fyodor Soikin
Nov 24 '18 at 20:55
I understand that projection should listen to the events. But I need to push the event (BudgetWasCreated) to that stream (an EventBus, for instance). But the event is created inside Budget (domain model) and stores in it. As long as I understand I can not inject EventBus into the domain model. So, how should I fire the event? For instance, I'll inject EventBus into the CreateBudgetHandler which handle CreateBudgetCommand. Is it fine to get events from the model and fire dispatch them one by one? Or is it better to inject EventBus into BudgetRepository since we already get events in it?
– vansanblch
Nov 25 '18 at 8:20
1
You can inject EventBus to CommandHandler or in EventStore that injected into Repository. After Saving all events in event store, you should publish stored events to world. Your projection may be listen sync or async to events that published.
– Morilog
Nov 26 '18 at 16:04
add a comment |
I'm trying to implement a simple CQRS+ES project to understand how it should work. The Prooph library is a way too complicated and has too many options.
As long as I understand I should have a CommandBus that will handle commands and execute domain logic. I've injected a Symfony's Messanger into a controller and it works. So, the aggregate root creates an event and apply it to a domain model. Then, the command handler has an injected repository that saves the domain (saves domain's events). But I can not get how should I update projection for this domain.
Here how a command handler looks like
class CreateBudgetHandler
{
private $budgetRepository;
public function __construct(
BudgetRepository $budgetRepository
) {
$this->budgetRepository = $budgetRepository;
}
public function __invoke(
CreateBudgetCommand $command
) {
$budget = Budget::create(
new BudgetId(Uuid::uuid4()),
new Amount($command->getBudget()->getAmount()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getStartDate()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getEndDate())
);
$this->budgetRepository->save($budget);
}
}
So, it simply gets a command, calls a named constructor for the domain model (Budget::create
) and passes it to a repository that will extract all recorded events and saves them into an event store database.
I'm wondering is it ok to inject another repository into the command handler that will save the domain model object into another table? Something like this
$this->budgetProject->insert($budget);
The insert
method will take a domain model, reads recorded events, transforms them into an INSERT/UPDATE/DELETE queries and runs them.
php symfony projection cqrs event-sourcing
I'm trying to implement a simple CQRS+ES project to understand how it should work. The Prooph library is a way too complicated and has too many options.
As long as I understand I should have a CommandBus that will handle commands and execute domain logic. I've injected a Symfony's Messanger into a controller and it works. So, the aggregate root creates an event and apply it to a domain model. Then, the command handler has an injected repository that saves the domain (saves domain's events). But I can not get how should I update projection for this domain.
Here how a command handler looks like
class CreateBudgetHandler
{
private $budgetRepository;
public function __construct(
BudgetRepository $budgetRepository
) {
$this->budgetRepository = $budgetRepository;
}
public function __invoke(
CreateBudgetCommand $command
) {
$budget = Budget::create(
new BudgetId(Uuid::uuid4()),
new Amount($command->getBudget()->getAmount()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getStartDate()),
DateTimeImmutable::createFromFormat('Y-m-d', $command->getBudget()->getEndDate())
);
$this->budgetRepository->save($budget);
}
}
So, it simply gets a command, calls a named constructor for the domain model (Budget::create
) and passes it to a repository that will extract all recorded events and saves them into an event store database.
I'm wondering is it ok to inject another repository into the command handler that will save the domain model object into another table? Something like this
$this->budgetProject->insert($budget);
The insert
method will take a domain model, reads recorded events, transforms them into an INSERT/UPDATE/DELETE queries and runs them.
php symfony projection cqrs event-sourcing
php symfony projection cqrs event-sourcing
asked Nov 24 '18 at 14:37
vansanblchvansanblch
1,09411329
1,09411329
1
Protection should be listening to the event stream independently, as a separate service, or at least separate subroutine inside the command processing service.
– Fyodor Soikin
Nov 24 '18 at 20:55
I understand that projection should listen to the events. But I need to push the event (BudgetWasCreated) to that stream (an EventBus, for instance). But the event is created inside Budget (domain model) and stores in it. As long as I understand I can not inject EventBus into the domain model. So, how should I fire the event? For instance, I'll inject EventBus into the CreateBudgetHandler which handle CreateBudgetCommand. Is it fine to get events from the model and fire dispatch them one by one? Or is it better to inject EventBus into BudgetRepository since we already get events in it?
– vansanblch
Nov 25 '18 at 8:20
1
You can inject EventBus to CommandHandler or in EventStore that injected into Repository. After Saving all events in event store, you should publish stored events to world. Your projection may be listen sync or async to events that published.
– Morilog
Nov 26 '18 at 16:04
add a comment |
1
Protection should be listening to the event stream independently, as a separate service, or at least separate subroutine inside the command processing service.
– Fyodor Soikin
Nov 24 '18 at 20:55
I understand that projection should listen to the events. But I need to push the event (BudgetWasCreated) to that stream (an EventBus, for instance). But the event is created inside Budget (domain model) and stores in it. As long as I understand I can not inject EventBus into the domain model. So, how should I fire the event? For instance, I'll inject EventBus into the CreateBudgetHandler which handle CreateBudgetCommand. Is it fine to get events from the model and fire dispatch them one by one? Or is it better to inject EventBus into BudgetRepository since we already get events in it?
– vansanblch
Nov 25 '18 at 8:20
1
You can inject EventBus to CommandHandler or in EventStore that injected into Repository. After Saving all events in event store, you should publish stored events to world. Your projection may be listen sync or async to events that published.
– Morilog
Nov 26 '18 at 16:04
1
1
Protection should be listening to the event stream independently, as a separate service, or at least separate subroutine inside the command processing service.
– Fyodor Soikin
Nov 24 '18 at 20:55
Protection should be listening to the event stream independently, as a separate service, or at least separate subroutine inside the command processing service.
– Fyodor Soikin
Nov 24 '18 at 20:55
I understand that projection should listen to the events. But I need to push the event (BudgetWasCreated) to that stream (an EventBus, for instance). But the event is created inside Budget (domain model) and stores in it. As long as I understand I can not inject EventBus into the domain model. So, how should I fire the event? For instance, I'll inject EventBus into the CreateBudgetHandler which handle CreateBudgetCommand. Is it fine to get events from the model and fire dispatch them one by one? Or is it better to inject EventBus into BudgetRepository since we already get events in it?
– vansanblch
Nov 25 '18 at 8:20
I understand that projection should listen to the events. But I need to push the event (BudgetWasCreated) to that stream (an EventBus, for instance). But the event is created inside Budget (domain model) and stores in it. As long as I understand I can not inject EventBus into the domain model. So, how should I fire the event? For instance, I'll inject EventBus into the CreateBudgetHandler which handle CreateBudgetCommand. Is it fine to get events from the model and fire dispatch them one by one? Or is it better to inject EventBus into BudgetRepository since we already get events in it?
– vansanblch
Nov 25 '18 at 8:20
1
1
You can inject EventBus to CommandHandler or in EventStore that injected into Repository. After Saving all events in event store, you should publish stored events to world. Your projection may be listen sync or async to events that published.
– Morilog
Nov 26 '18 at 16:04
You can inject EventBus to CommandHandler or in EventStore that injected into Repository. After Saving all events in event store, you should publish stored events to world. Your projection may be listen sync or async to events that published.
– Morilog
Nov 26 '18 at 16:04
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53459238%2fthe-valid-place-to-inject-a-projection-service-to-handle-domain-objects-or-event%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53459238%2fthe-valid-place-to-inject-a-projection-service-to-handle-domain-objects-or-event%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Protection should be listening to the event stream independently, as a separate service, or at least separate subroutine inside the command processing service.
– Fyodor Soikin
Nov 24 '18 at 20:55
I understand that projection should listen to the events. But I need to push the event (BudgetWasCreated) to that stream (an EventBus, for instance). But the event is created inside Budget (domain model) and stores in it. As long as I understand I can not inject EventBus into the domain model. So, how should I fire the event? For instance, I'll inject EventBus into the CreateBudgetHandler which handle CreateBudgetCommand. Is it fine to get events from the model and fire dispatch them one by one? Or is it better to inject EventBus into BudgetRepository since we already get events in it?
– vansanblch
Nov 25 '18 at 8:20
1
You can inject EventBus to CommandHandler or in EventStore that injected into Repository. After Saving all events in event store, you should publish stored events to world. Your projection may be listen sync or async to events that published.
– Morilog
Nov 26 '18 at 16:04