First, note that if we connect the controller directly to the command handler, we face a similar problem:
public function createPost($req, $resp) { $command = new CreatePostCommand($command->getTitle(), $command->getContent()); $this->createPostCommandHandler->handle($command);
The bus introduces an indirection layer that allows you to separate the controller from the event handler, but the problem you are facing is more fundamental.
I am not sure how to do it here.
TL; DR - tell the domain which identifiers to use, and not ask the domain which identifier was used.
public function createPost($req, $resp) { // TADA $command = new CreatePostCommand($req->getPostId() , $command->getTitle(), $command->getContent()); $this->createPostCommandHandler->handle($command); // happy path: redirect the client to the correct url $this->redirectTo($resp, $postId) }
In short, the client, not the domain model or persistence level, is responsible for creating the identifier of the new object. The application component can read the identifier in the command itself and use it to coordinate the next state transition.
The application in this implementation simply translates the message from the DTO view to the domain view.
An alternative implementation uses the command identifier and deduces identities from this command that will be used
$command = new CreatePostCommand( $this->createPostId($req->getMessageId()) , $command->getTitle(), $command->getContent());
Named UUIDs are a common choice in the latter case; they are deterministic and have low probability of collisions.
Now this answer is a bit of a hoax - we really only demonstrated that in this case we do not need the result from the command handler.
In general, we would rather have one; Post / Redirect / Get is a good idiom to use to update a domain model, but when a client receives this resource, we want to make sure that they get a version that includes the changes they just made.
If your readings and notes use the same book of notes, this is not a problem. Everything you read is always the latest version.
However, cqrs is a common architectural pattern in domain design, in which case the recording model (message processing) will be redirected to the readable model, which usually publishes outdated data. This way you can include the minimum version in the get request so that the handler knows to update its obsolete cache.
Is there an elegant way to return message data in response?
Here is an example in the sample code that you provided with your question:
public function createPost($req, $resp)
Think about it: $ req is an HTTP request message that is similar to your command, and $ resp is essentially a data structure descriptor into which you can write your result.
In other words, pass a callback or result descriptor with your command, and let the command handler fill in the details.
Of course, it depends on your bus supporting callbacks; not guaranteed.
Another possibility, which does not require changing the signature of your command handler, is to arrange for the controller to subscribe to events published by the command handler. You coordinate the correlation identifier between the team and the event and use this to pull the desired result event.
Specificity does not matter much - an event created during processing of a command can be written to the message bus or copied to a mailbox or ...