4

I have a Doctrine Event Listener that listens to the onFlush event. I use it to update an eTag on an entity when saved.

I need to get access to the entities scheduled for deletion, so I can access their associated object, however:

I'm using a soft-deletable filter, so the entities aren't actually in $uow->getScheduledEntityDeletions(), they're in $uow->extraUpdates marking the deleted flag changed instead.

This variable is private and I don't know of any programatic way to get notified of this change. Any ideas?

private function updateIfRequired(OnFlushEventArgs $args)
{
    $em     = $args->getEntityManager();
    $uow    = $em->getUnitOfWork();



    // Entities either updated or just inserted
    $upsertedEntities = array_merge(

        $uow->getScheduledEntityUpdates(),
        $uow->getScheduledEntityInsertions()
    );

    foreach ($upsertedEntities as $entity) {

        if ($entity instanceof ETaggableInterface || $entity instanceof ETagRelatedInterface) {
            $this->updateETag($entity);
        }
    }

    // When soft-deleted, this and getScheduledEntityUpdates are both empty!
    $deletedEntities = $uow->getScheduledEntityDeletions();

    foreach ($deletedEntities as $entity) {

        $this->deletedEntities[spl_object_hash($entity)] = $entity;
        $this->updateETag($entity);
    }

}
Adam
  • 5,091
  • 5
  • 32
  • 49

2 Answers2

5

So, the detailed answer for this question would be something like this:

Listen to the preSoftDelete event (Symfony2 DoctrineExtensions preSoftDelete event call):

    tags:
        - { name: doctrine.event_listener, event: preSoftDelete }

Then in your listener class, add the following method:

public function preSoftDelete(LifecycleEventArgs $args){
    $entity = $args->getEntity();
    $em = $args->getEntityManager();

    if ($entity instanceof ETaggableInterface || $entity instanceof ETagRelatedInterface) {
        $entity->updateEtag('foo'); // Was not clear what $this->updateEtag() do

        $em->persist($entity);
        $classMetadata = $em->getClassMetadata(get_class($entity));
        $em->getUnitOfWork()->computeChangeSet($classMetadata, $entity);
    }
}

This will update the entity, tell to persist it, calculate the changes.

Community
  • 1
  • 1
totophe
  • 2,961
  • 1
  • 15
  • 12
  • Nice. Thanks for sharing. You're right, `$this->updateEtag()` was a method in the same class that I omitted for brevity. You can find a more detailed version of what I ended up implementing here (roughly speaking): https://gist.github.com/adamquaile/0733417e1d6a9c98ed27 – Adam Sep 29 '14 at 19:42
0

Maybe you should listen to preSoftDelete events: https://github.com/Atlantic18/DoctrineExtensions/blob/master/lib/Gedmo/SoftDeleteable/SoftDeleteableListener.php#L74

coma
  • 16,429
  • 4
  • 51
  • 76
  • I did look for that and didn't find it. I actually solved it a different way by listening to other lifecycle events to get the affected entities and scheduling the updates in a batch onFlush. Will accept as answer though as that's what i was looking for. – Adam Apr 10 '14 at 17:35