[TYPO3-mvc] Issues with "@cascade remove" and forms with nested objects

Frenck Lutke frenck at innologi.nl
Tue May 21 10:28:40 CEST 2013


Hi Franz,

I'm well familiar with this issue, as I had to debug it a long time ago 
as well.

On 19-5-2013 18:15, Franz Koch wrote:
> Situation:
> I just wrote a simple blog like extension for a customer with the
> possibility to upload pictures and assign a caption to them. The
> pictures are themselves a domain object holding a filename and a caption
> property and are connected to the post object as ObjectStorage.
> In the create and edit forms, the blogger can dynamically add more
> upload fields with caption and ofc edit/delete existing.
>
> Issue:
> This all is working fine and gets mapped and persisted correctly as long
> as I haven't set the "@cascade remove" annotation for the pictures
> property. As soon as I add the annotation, ALL already persisted
> pictures get deleted when I update the blog post even if nothing changed
> at all and the property is correctly filled.
>
> Possible bug/cause:
> After debugging this for some hours now I think I found the cause. When
> I update the modified post in the repository, the persistence backend is
> calling "getRemovedChildObjects" in it's "persistObjectStorage" method,
> and "getRemovedChildObjects" always returns ALL contained objects even
> when nothing got removed.
> All this method internally does is a simple check if the current
> objectStorage contains all objects that exist in the clean property by
> comparing their spl_object_hash and returns all that are not contained.
> And this is the issue, because all nested picture objects got cloned in
> the PropertyMapper as they where submitted via the edit form and thus
> have a different spl_object_hash. So either the "getRemovedChildObjects"
> has to compare the (U)UID in case of DomainObjects or the PropertyMapper
> must not clone any object which is no aggregate root and thus not
> monitored by the persistenceManager.
>

This happens because the objectStorage property has changed. The tricky 
part is: all extbase knows is that the objectStorage has changed. It 
doesn't know which child-objects are detached, because child-objects 
aren't set to be removed when detached, as you could still attach them 
somewhere else before persistence applies. Detaching a child-object 
doesn't "say" anything about the child-object, it only says something 
about the its relation to the parentobject, and that's not stored in the 
child-object.

Extbase's way to deal with this, is to simply set the entire ORIGINAL 
objectStorage content as removed as you've noticed, and then and 
reattach the child-objects that were in the changed objectStorage, while 
in turn removing re-attached child-objects from the removedObjects 
storage. This way, only child-objects that weren't re-attached can be 
considered "lost children" and remain in the removedObjects storage.

While that method is an acceptable solution in itself, the problem that 
occurs is that there is a cascade remove check in persistObjectStorage() 
BEFORE the re-attachment, that doesn't differentiate between removing 
always or only if the parent object was removed. It is this that I would 
classify as the actual bug, as "cascade" implies a status passed down 
from the parent object in programming.

Cheers,
Frenck


More information about the TYPO3-project-typo3v4mvc mailing list