在Symfony 2.6上使用Doctrine是否有一种方法可以"检测"到已持久化的实体上的事务回滚?
我最初的问题:我创建了代表文件系统上的文件的新实体。在$em->persist()
上,这些实体将文件从/temp
目录移动到最终目的地vía Doctrine的PrePersist事件。如果我正在处理的事务在稍后的代码中回滚,则数据库上没有创建行,但是文件徘徊,每次我这样做时,我都必须在$em->rollback()
之后用额外的代码手动删除它们。所以我想可能有一个事件我可以用来检测一个实体已经从变更列表中"删除"或"回滚",所以我可以删除实体的相关文件。
也: PostPersist或PostFlush事件似乎解决了我的问题,但是如果我有几个$em->flush()
指令,其中一个在代码中抛出异常,并且我在整个事务上执行$em->rollback()
,我仍然得到挥之不去的文件
Doctrine默认没有回滚事件。但是您可以做的是扩展Connection类并抛出您自己的事件:
<?php
namespace Acme'MyBundle'Doctrine'DBAL;
use Doctrine'DBAL'Connection;
use Ozean12'ApiSDKBundle'Doctrine'Event'PostCommitEventArgs;
use Ozean12'ApiSDKBundle'Doctrine'Event'PostRollbackEventArgs;
/**
* 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());
}
}
}
然后将该类声明为连接包装器:
doctrine:
dbal:
wrapper_class: Acme'MyBundle'Doctrine'DBAL'ConnectionWrapper
创建您的事件类和订阅者。您可以通过监听onFlush事件来跟踪同一订阅者类中的持久实体,以便在提交或回滚发生时对它们执行操作。
对于那些来这里的人:我添加了PR -让我们希望它会被接受。
https://github.com/doctrine/dbal/pull/4622使用EntityManager的连接开始事务,然后通过Doctrine执行db工作,并在成功度量时提交或在失败度量时回滚。
$conn = $entityManager->getConnection();
$conn->beginTransaction();
/*
Your work here
*/
// if success
$conn->commit();
// else failure
$conn->rollback();