The valid place to inject a projection service to handle domain objects or events












0















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.










share|improve this question


















  • 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
















0















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.










share|improve this question


















  • 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














0












0








0


0






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.










share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 24 '18 at 14:37









vansanblchvansanblch

1,08411329




1,08411329








  • 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





    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












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
});


}
});














draft saved

draft discarded


















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
















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

TypeError: fit_transform() missing 1 required positional argument: 'X'