我刚注意到Doctrine事件系统的奇怪行为。在我阅读的文档中,我读到了preFlush
事件:
在preFlush
之前调用{p>EntityManager#flush()
听起来不错。但是当我创建事件订阅者时,我发现有些错误 - preFlush
发生了两次,而onFlush
和postFlush
只发生过一次(我假设preFlush
也发生过一次)。
有趣的是,每次preFlush
计算变更集时都会调用UnitOfWork
- 等于当前管理实体的数量。
这是一个简单的例子(Doctrine 2.4,我没有使用Symfony):
// event subscriber class:
class Subscriber implements EventSubscriber {
public function getSubscribedEvents() {
return array(Events::preFlush, Events::onFlush, Events::postFlush);
}
public function preFlush() {
echo '********** PRE FLUSH ***********' . "\n";
}
public function onFlush() {
echo '********** ON FLUSH ***********' . "\n";
}
public function postFlush() {
echo '********** POST FLUSH ***********' . "\n";
}
}
// test:
$em->getEventManager()->addEventSubscriber(new Subscriber());
for($i = 0; $i < 5; $i++) {
echo 'i = ' . $i . "\n";
$u = new Unit(); // Unit is sample entity - very simple one with no associations
$u->setName('unit');
$u->setSymbol('u');
$em->persist($u);
$em->flush();
}
产生输出:
i = 0
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** ON FLUSH ***********
********** POST FLUSH ***********
i = 1
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** ON FLUSH ***********
********** POST FLUSH ***********
i = 2
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** ON FLUSH ***********
********** POST FLUSH ***********
i = 3
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** ON FLUSH ***********
********** POST FLUSH ***********
i = 4
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** PRE FLUSH ***********
********** ON FLUSH ***********
********** POST FLUSH ***********
因此,当preFlush
实际刷新时,每个管理实体(包括新实体)调用一次EntityManager
。
在我看来preFlush
事件应该按EntityManager#flush()
操作调用一次(就像其他刷新事件一样)。
我发现代码产生了这种行为:https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php#L536
这是我的问题:我错了,Doctrine工作不正确还是我还缺少其他东西?
答案 0 :(得分:1)
我不知道这是否是故意的,但似乎合乎逻辑。 PreFlush
调用的数量与托管实体的数量相匹配,但可能是因为该方法旨在允许您强制实体的完整性。
请注意PostFlush
来电的数量不会增加。如果每个实体的数据在刷新时发生变化,那么每个实体的数据将再次被调用{/ 1}。
理想情况下,不带参数的PostFlush
只应在脚本执行结束时调用(或至少几次调用)。为了确保在调用特定实体时对其进行处理和刷新,请将实体作为参数传递给$em->flush()
方法。
答案 1 :(得分:1)
preFlush
时都会触发 $em->flush()
。只有在提交实际变更集时才会触发postFlush
。有关如何更改此postFlush
行为的讨论,请参阅https://github.com/doctrine/doctrine2/pull/382。