FLOW3: Updating entities inside an aggregate

The manual explains how to update entities that are accessible via a repository, but it does not say explicitly how to update an entity within an aggregate. In this post, I’ll show which steps need to be taken to do that.

Assume you have the following to models: Foo and Bar, and Foo contains an SplObjectStorage of Bars. Foo is the aggregate root and has its own FooRepository. Bar should not be accessible from the outside but only through traversal via Foo. Now, how to update a Bar object? Obviously, you can’t do $this->barRepository->update($bar); because there is no bar repository!

So, let’s start by looking at the controller and the views. Create basic index, new, create, edit and save actions. All of these need a $foo as an argument (additonally to the $bar that you want to create/edit/update). So you need to give all links (or forms) in the views arguments={foo: foo}.

The controller then needs to set the < code >$bar in the $foo. When creating, this could be $foo->addBar($bar).
For updating, I suggest calling $foo->updateBar($bar).

Of course you need to implement these to methods in the model Foo. addBar() is easy, just attach the given $bar to the SplObjectStorage of Bars. updateBar() is a little more complicated, because you first need to find out which of the items in the SplObjectStorage needs to be replaced. This can be done with the following code:

$editedBarIdentifier = »
$this->persistenceManager->getIdentifierByObject($editedBar);
$originalBar =  $this->persistenceManager-> »
getObjectByIdentifier($editedBarIdentifier);
$this->bars->detach($originalBar);
$this->bars->attach($editedBar);

As you can see, that requires a persistence manager object, which can be injec ted via dependency injection in the model. Make sure to set the @transient annotation to tell the persistence framework that you don't want it to track the persistence manager object (of course!).

That's it. Happy updating!

filed under , posted on March 8, 2010

Comments are closed.