What is the correct use of $ unitOfWork-> getScheduledCollectionDeletions () in Doctrine 2 (and Symfony)?

I am trying to detect many-to-many relationships in an onFlush event.

If new relationships are added to the relationship or updating the relationship (always preserving the element), I can detect the changes using $unitOfWork->getScheduledCollectionUpdates() and then check for getInsertDiff() or getDeleteDiff() . So far so good.

The problem arises when I take all the entities from the relationship: "Previously, there were two related entities, but now there are NO entities.

When the relation remains empty, I can access $unitOfWork->getScheduledCollectionDeletions() , but there is no way to find out which objects were deleted:

  • getDeleteDiff() for these collections says nothing.
  • getSnapshot() doesn't tell me which objects were there before

How do you know which objects were deduced from the many-to-many relationship?


I added a Gist with a full implementation: everything works fine (optimization may need to be), except for $uow->getScheduledCollectionDeletions() (line 101)

https://gist.github.com/eillarra/5127606

+4
source share
1 answer

The cause of this problem is twofold:

1) When the clear() method is called on Doctrine\ORM\PersistentCollection , it will be:

  • clear your internal set of objects.
  • calling scheduleCollectionDeletion() on Doctrine\ORM\UnitOfWork .
  • take a new picture of yourself.

Number 2 is the reason your collection is displayed in $uow->getScheduledCollectionDeletions() (and not in $uow->getScheduledCollectionUpdates() ). Number 3 is the reason you cannot determine what was in the collection before it was cleaned.

2) When using the Symfony2 Form component, in particular the ChoiceType or CollectionType types in combination with the multiple option, this clear() method is called when all objects must be removed from the collection.

This is due to the addition of MergeDoctrineCollectionListener : https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php#L55

This is done as an optimization: it cleans the collection faster in this way, instead of checking which objects should be removed from it.

I can think of two possible solutions :

1) Create a fork symfony/symfony and implement the option so as not to add a MergeDoctrineCollectionListener . Perhaps something like no_clear to prevent the addition of a listener. This will not break BC and solve your problem, because the clear() method of the collection will not be called when all objects have to be deleted.

2) Redesign your meter. You may also listen to the OnLoad event, which can count the number of objects in the collection at the moment it is retrieved from db. Thus, your OnFlush listener can use this number to find out how many objects were removed from the collection when it was cleared.

+6
source

All Articles