在doctrine-mongodb中的preUpdate事件中创建/持久保存新文档

时间:2014-05-29 07:23:50

标签: php mongodb doctrine-odm odm doctrine-mongodb

我正在使用doctrine-mongodb-odm-1.0.0-BETA10并尝试在\InitialDocument事件运行时根据preUpdate提供一些自定义逻辑。

让我们说\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事件,但它不会在db中保留新文档。并且postPersist事件将永远不会被解雇。

还有一些自定义逻辑,但都在事件范围内。在某些时候,逻辑可能抛出一个Exception,它必须停止InitialDocument的更新事件,因此InitialDocument状态取决于业务范围内的\StateDocument创建过程。

我该如何解决这个问题?在changeSet重新计算之前运行的preFlush事件不会确定InitialDocument实例。所以这是"搜索"在preFlush更新并让我认为这不是正确的方法。请用适当的建议告诉我。感谢。

1 个答案:

答案 0 :(得分:4)

我为您的用例here创建了一个测试用例。从您的问题中的代码中脱颖而出的一件事是,您在生命周期回调期间没有在正在修改的文档上调用recomputeSingleDocumentChangeSet(),如preUpdate documentation中所述。但即使使用该调用,也不会插入新文档。这是因为UnitOfWork在插入和upsert之后执行更新。完整订单可以在UnitOfWork's commit() method中找到:

  • 文档upserts
  • 文件插入
  • 文档更新
  • 额外更新(由persister类在内部安排)
  • 收集删除
  • 收藏更新
  • 文件删除

调度preUpdate事件时,已经发生了新文档的upserts /插入。即使调用recomputeSingleDocumentChangeSet(),您最终也会安排文档进行插入,但UnitOfWork会忽略这一点,并在清除所有计划队列here时最终取消设置。

虽然一个简单的解决方案是ODM在处理更新后检查其他插入,但在某些情况下可能会导致无限循环。 UnitOfWork排序早于我在项目上的工作,但是当构思原始实现时,我可能会担心循环的风险。

作为一种解决方法,您可能希望让侦听器转储要插入到其他容器(或侦听器本身)中的新文档,然后在事实之后检查是否要保留/刷新其他文档。