Php 在doctrine mongodb中预更新事件时创建/持久化新文档
我正在使用Php 在doctrine mongodb中预更新事件时创建/持久化新文档,php,mongodb,doctrine-odm,odm,doctrine-mongodb,Php,Mongodb,Doctrine Odm,Odm,Doctrine Mongodb,我正在使用doctrine-mongodb-odm-1.0.0-BETA10并试图在预更新事件运行时提供一些基于\InitialDocument的自定义逻辑 假设\InitialDocument获得了一些状态,这些状态必须作为新\StateDocument的初始状态。我在做这样的事情: class InitDocListener implements \Doctrine\Common\EventSubscriber { public function getSubscribedEvent
doctrine-mongodb-odm-1.0.0-BETA10
并试图在预更新
事件运行时提供一些基于\InitialDocument
的自定义逻辑
假设\InitialDocument
获得了一些状态,这些状态必须作为新\StateDocument
的初始状态。我在做这样的事情:
class InitDocListener implements \Doctrine\Common\EventSubscriber {
public function getSubscribedEvents()
{
return [
Events::preUpdate
];
}
public function preUpdate($args){
$document = $args->getDocument();
if($document instanceOf InitialDocument && $document->getState() == 'mine'){
$stateDocument = new \StateDocument();
$stateDocument->setInitDocument($document);
$args->getDocumentManager()->persist($stateDocument);
//no flush cause recursion happens
}
}
}
prePersist
事件由\StateDocument
发生,但它不会将新文档持久保存在数据库中。和postPersist
事件将永远不会触发
还有一些自定义逻辑,但都在事件范围内。在某一点上,逻辑可能引发异常,该异常必须停止InitialDocument
的更新事件,因此InitialDocument
状态取决于业务范围内的\StateDocument
创建过程
我怎样才能解决这个问题<在更改集重新计算之前要运行的代码>预刷新事件不确定
初始文档
实例。因此,在preFlush
上“搜索”更新是一种伎俩,让我觉得这不是正确的方法。请给我一个合适的建议。谢谢。我为您的用例创建了一个测试用例。问题中代码中突出的一点是,您没有在生命周期回调期间对要修改的文档调用重新计算SingleDocumentChangeSet()
,如中所述。但即使有了这个调用,新文档也不会被插入。这是因为UnitOfWork在插入和升级之后执行更新。完整顺序见:
- 文件升级
- 文件插入
- 文件更新
- 额外更新(由持久化类在内部安排)
- 集合删除
- 收藏更新
- 文件删除
preUpdate
事件时,新文档的追加/插入已经发生。即使调用了重新计算SingleDocumentChangeSet()
,最终也会安排文档插入,但UnitOfWork会忽略这一点,并在清除所有计划队列时最终将其取消设置
虽然一个简单的解决方案是ODM在处理更新后检查额外的插入,但在某些情况下,这可能会导致无限循环。UnitOfWork排序早于我在项目中的工作,但我认为在最初的实现构思时,循环的风险可能是一个问题
作为一种解决方法,您可能希望侦听器转储要插入到其他容器(或侦听器本身)中的新文档,然后在事后检查是否有其他文档需要持久化/刷新。我为您的用例创建了一个测试用例。问题中代码中突出的一点是,您没有在生命周期回调期间对要修改的文档调用
重新计算SingleDocumentChangeSet()
,如中所述。但即使有了这个调用,新文档也不会被插入。这是因为UnitOfWork在插入和升级之后执行更新。完整顺序见:
- 文件升级
- 文件插入
- 文件更新
- 额外更新(由持久化类在内部安排)
- 集合删除
- 收藏更新
- 文件删除
preUpdate
事件时,新文档的追加/插入已经发生。即使调用了重新计算SingleDocumentChangeSet()
,最终也会安排文档插入,但UnitOfWork会忽略这一点,并在清除所有计划队列时最终将其取消设置
虽然一个简单的解决方案是ODM在处理更新后检查额外的插入,但在某些情况下,这可能会导致无限循环。UnitOfWork排序早于我在项目中的工作,但我认为在最初的实现构思时,循环的风险可能是一个问题
作为一种解决方法,您可能需要让侦听器转储要插入到其他容器(或侦听器本身)中的新文档,然后在事后检查是否需要保留/刷新其他文档。谢谢。昨天我和UnitOfWork玩了一段时间,得出了类似的结论。您刚刚确认了这样一个假设:在这种情况下,我们需要在其他容器中处理插入文档。问题是,
preUpdate
事件会导致新文档的托管状态在提交时和提交后保持不变//清除其上游(和其他内容)。文档保持已知状态并声明为托管状态,但在对该文档进行新的持久化/刷新时会导致错误。因此,我尝试将flush()
包装起来,以在提交后处理自己的自定义事件(在清除后
),并再次添加scheduleForUpsert以防止执行持久化()
。但它没有起作用。现在我正试图放弃preUdpate
,完全支持我的afterCommit
。如果问题在GitHub中得到批准,将带来一些(故障转移?)测试。决定放弃preUpdate
事件,以支持wrapped flush,并在新文档持久化应用程序逻辑出现故障时实现具有回滚行为的afterCommit
事件。队列:1<代码>预更新
验证初始文档并进行更改设置以进行回滚。2.afterUpdate
将文档附加到updated\u docs集合
。3afterCommit
事件触发基于updated_docs_collection
创建新文档,并在失败时刷新它们或回滚更新的文档。这不是一个很好的实现,但目前仍然有效。谢谢。昨天我和UnitOfWork玩了一段时间,得出了类似的结论。你刚刚加入了