Closed djkoza closed 5 years ago
The error message and the 1st line of your trace tell you what is wrong.
#0 /app/src/Domain/Stream/Event/StreamWasCreated.php(51):
App\Domain\Stream\Event\StreamWasCreated->__construct(
Object(Ramsey\Uuid\Uuid),
Array, // <==== should be of type UserViewInterface
Object(App\Domain\Stream\ValueObject\Parameters)
)
The 2nd parameter given to the constructor of StreamWasCreated have to be of type UserViewInterface but in your case it's an array.
return new self(
Uuid::fromString($data['uuid']),
$data['user'],
Parameters::fromArray($data['parameters'])
);
you need to deserialize $data['user']
. it's an array.
I will advice you to use Id/Uuid instead of UserviewInterface and add other user informations when running a projection into the read model.
Here is my trick to handle serialization of fields independantly : https://github.com/jorge07/symfony-4-es-cqrs-boilerplate/issues/87
But according to @jorge07 it's better to let a serializer handle it for you (jms_serializer, symfony/serializer, ...)
Hi @djkoza
Your StreamWasCreated event is passing an array as Object. You need to deserialise User before pass it to the constructor.
/**
* @throws \Assert\AssertionFailedException
*/
public static function deserialize(array $data): self
{
Assertion::keyExists($data, 'uuid');
Assertion::keyExists($data, 'user');
Assertion::keyExists($data, 'parameters');
return new self(
Uuid::fromString($data['uuid']),
- $data['user'],
+ User:: deserialize($data['user']),
Parameters::fromArray($data['parameters'])
);
}
Also, I do not recommend use Projections in DomainEvents. A Projection is just a representation of the model, not the model itself. Use a domain object instead.
Thanks a lot for your reply @blixit @jorge07
you need to deserialize
$data['user']
. it's an array.
When I call CreateStreamCommand this is UserView object. But when I call (after save) to fetch
$stream = $this->streamRepository->get($command->uuid);
Then I get mentioned error and in this moment $data['user']
it's an array - empty.
When I serialize with UserView::serialize()
return [
'uuid' => $this->getId(),
'credentials' => [
'email' => (string) $this->credentials->email,
],
];
I have got error from doctrine about cascade persisting UserView. So, as I mentioned
So my second try was serialize User object, but then I can't save Stream object, because doctrine thinks user is new object and try to cascade persist.
@blixit
I will advice you to use Id/Uuid instead of UserviewInterface and add other user informations when running a projection into the read model.
I tried this solution, but where is the best place code to fetch User from repository and assign them to Stream on create or update record? This must have happened before persist, because
doctrine thinks user is new object and try to cascade persist.
@jorge07
Also, I do not recommend use Projections in DomainEvents. A Projection is just a representation of the model, not the model itself. Use a domain object instead.
if I understand correctly, my relation is needed to rebuild: "target-entity" not point to Projections, but to Domain objects?
And how I can get User Domain Object, not Projection?
Newbie questions, I'm new in DDD
Thanks a lot ;)
I'll create a branch with a similar use case will be easier for others to look at this and see how to start or process with things like that.
I tried this solution, but where is the best place code to fetch User from repository and assign them to Stream on create or update record
When you are creating your object I guess you already know what user to attach to it. You could fetch the user when handlind the command (inside the ~CreateStreamCommand~ CreateStreamCommandHandler).
@jorge07 this will be very helpful, I will be patient. @blixit ok, that's fine - but what with doctrine problem? I can't persist and flush Stream object because related User object is trying to persist too. As we know, User already exist and database fail to execute this insert (create) or update command.
related User object is trying to persist too
this is a known issue with doctrine. you need to properly set your 'cascade' properties (on persist, on update, ...). it's not due to es-cqrs
@blixit I found some solutions, 1) merge() via entity manager 2) fetch User (related object) (on deserialize) from orm and call setUser on Stream object 3) use JMSSerializerBundle and Doctrine object constructor
What is the best way to deal with this problem?
i use to use the 2nd solution and the 1st one in this order.
@blixit ok, but some question - how can I get repository in StreamWasCreated event or in StreamView Projection? We don't call this classes via service, so dependency injection dosent work. How to deal with that? I want to fetch related object in deserialize operation
How can I get repository in StreamWasCreated event or in StreamView Projection I think it's a bad design. (Maybe you mean the event handler.)
I think the goal of the :
You should not call repository at this place. I suggest you to fetch related objects from the commandhandler. For instance:
$command->setUser($relatedUser)
::register(..., $command->getUser(), ...)
StreamWasCreated(.., $userView, ...)
Hi @blixit @djkoza,
I made this branch with an example of user relations and a way to minimise the couple between bounded contexts.
I think we can close it. Feel free to reopen it if needed it.
Hi, I have some problems with save and fetch object with related field, but some example: 1) User 2) Stream
Stream has owner User, so mapping:
stream
user
I want to create new stream, related to User. So, I create CreateStreamCommand and Handler, like this:
register method from StreamFactory
create method from Stream
And StreamWasCreated Event
At this step I don't serialize user, and everything is fine. But... When I want to get this Stream record, I see error:
I checked second argument, and it is empty array. So I think, problem is in unserialize event data.
So my second try was serialize User object, but then I can't save Stream object, because doctrine thinks user is new object and try to cascade persist.
What is the propper way to work with relationship?
Sorry my english ;)