Command template in php applications: how to handle controller actions?

I think this is more of a general question (rather than php restriction) regarding ddd and command template.

Let's say I execute CreatePostCommand from the create action of my controller, the command will be processed and ultimately successfully executed. How can I notify the dispatcher about what response to return in case of unsuccessful or successful command? Given that the command handler fires a domain-specific event, I could connect the controller to the event, but it seems rather inconvenient, also not suitable for each situation (for example, a message can be created somewhere else, and the controller really doesn’t find out about it :)).

public function createAction($title, $content) { $this->commandBus->execute(new CreatePostCommand($title, $content); $this->render('…'); // what if the command execution failed? } 

Any thoughts on this?

+6
source share
2 answers

I think that if you are really trying to follow the DDD command pattern, you need to treat the command bus like fire and forget the asynchronous process, which can take a lot of time.

Consider immediately the redirection to the command verification controller. It is up to the team verifier to actively check the status of the team and see if it works.

In most cases, the command will complete successfully, and your verifier can then redirect again to continue the normal flow.

If the command fails, the verifier places an appropriate error message.

If the command is executed, you can run the entire redirect cycle, informing the user that the command is being executed.

Sort of:

 // Execute the command $command = new CreatePostCommand($title, $content); $this->commandBus->execute($command); return redirect '/command-verifier/' . $command->getId(); // The verification action public function verifyCommandAction($commandId) $commandStatus = $this->commandBus->getStatus($commandId); if ($commandStatus == SUCCESS) redirect to all is well; if ($commandStatus == FAILED) then oops; if ($commandStatus == IN_PROGRESS) then maybe pause a bit and redirect again while keeping the user informed. 

It’s clear that a lot of hand span is happening, but I think this is the most general approach, especially with php, where each request starts from zero zero.

+1
source

The way I am doing this now is as follows (sorry long post).

 public function createAction($title, $content) { try { $post = $this->commandBus->execute(new CreatePostCommand($title, $content); } catch (Exception $e) { return $this->render('some error template file', $e); } return $this->render('successful creation template file', $post); } 

This way you create the message, and if everything goes as planned, return the $ post object and send it to your view. On the other hand, when an exception is thrown at runtime, you detect this error and send it to the view.

My preferred way is to force the controller to call a method for the service that controls this behavior, and introduce the controller as a listener that manages the responses, i.e.:

 public function createAction($title, $content) { $service = new CreateActionService($title, $content); return $service->create($this); } public function onError(Exception $e) { return $this->render('some error template file', $e); } public function onSuccess($post) { return $this->render('success', $post); } 

Then at your service ...

 public function create($listener) { try { $this->commandBus->execute(new CreatePostCommand($title, $content); } catch (Exception $e) { return $this->listener->onError($e); } return $this->listener->onSuccess($post); } 

In this way, your service manages the various results that the command handler can return, and your controller remains just to manage the responses that you might want to return to the presentation level.

0
source

Source: https://habr.com/ru/post/974464/


All Articles