Skip to content
Advertisement

is there a Doctrine rollback event? i.e. do stuff to entities on a changelist where there’s a rollback

working with Doctrine on Symfony 2.6 is there a way to ‘detect’ a transaction rollback on entities that have been persisted?

my original problem: I create new entities which represent files on the filesystem. On $em->persist() those entities move files from /temp directory to final destiantion vía Doctrine’s PrePersist event. If the transaction I’m working on is rolled back later in the code, no rows are created on the database, but the files linger and I have to manually delete them after the $em->rollback() with extra code, every time I do this. So I thoguht there might be an event I can use to detect an entity has been ‘removed’ from the changelist or ‘rolledback’, so I can delete the entity’s related file.

also: PostPersist or PostFlush event would seem to solve my problem, but if I have several $em->flush() instructions and one that’s below in the code throws an exception, and I do $em->rollback() on the whole transaction, I still get the lingering files

Advertisement

Answer

There is no rollback event in Doctrine by default. But what you can do, is to extend the Connection class and throw your own event:

<?php

namespace AcmeMyBundleDoctrineDBAL;

use DoctrineDBALConnection;
use Ozean12ApiSDKBundleDoctrineEventPostCommitEventArgs;
use Ozean12ApiSDKBundleDoctrineEventPostRollbackEventArgs;

/**
 * Class ConnectionWrapper
 */
class ConnectionWrapper extends Connection
{
    /**
     * {@inheritdoc}
     */
    public function commit()
    {
        parent::commit();

        if (!$this->isTransactionActive()) { // to be sure that we are committing a top-level transaction
            $this->getEventManager()->dispatchEvent(PostCommitEventArgs::NAME, new PostCommitEventArgs());
        }
    }

    /**
     * {@inheritdoc}
     */
    public function rollBack()
    {
        parent::rollBack();

        if (!$this->isTransactionActive()) { // to be sure that we are rolling-back a top-level transaction
            $this->getEventManager()->dispatchEvent(PostRollbackEventArgs::NAME, new PostRollbackEventArgs());
        }
    }
}

Then declare this class as a connection wrapper:

doctrine:
  dbal:
    wrapper_class:  AcmeMyBundleDoctrineDBALConnectionWrapper

And create your event classes and subscriber. You can track the persisted entities in the same subscriber class by listening to the onFlush event so you can perform the actions on them when commit or rollback happens.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement