我有一个包含两个生命周期事件方法的事件订阅者:prePersist和preUpdate。 prePersist正在按预期工作 - 我修改了文档,稍后在检索文档时会反映这些更改。但是,preUpdate没有按预期工作。这基本上是它的样子:
/**
* Also update the foo code when the bar profile is updated.
* @param LifecycleEventArgs $args
*/
public function preUpdate(LifecycleEventArgs $args)
{
$document = $args->getDocument();
if ($document instanceof BarProfile) {
$document->setFooCode('Salamanders');
}
}
如果我创建一个文档并将其fooCode设置为perPersist函数中的'placeholder',那么当我稍后检索文档时,fooCode就是'placeholder'。如果我然后更新它,并再次检索它,那么我希望它的fooCode是'Salamanders'。但是,它仍然是“占位符”。我甚至尝试将error_log()
内容放在那里,并将内容写入日志,以便我可以看到正在执行此方法。
我需要在$document->setFooCode()
之后做第二步才能使fooCode的新值保持不变?
答案 0 :(得分:2)
您无法直接在preUpdate
事件中修改字段,您必须修改其原始值。不允许对关联进行更改。你必须这样做:
$eventArgs->setNewValue('fooCode', 'Salamanders');
您声明“prePersist正在按预期工作 - 我修改了文档,稍后在检索文档时会反映这些更改。”
这让我相信你可能没有意识到持久性和更新之间的区别。在Doctrine中,第一次创建对象时会出现持久性。当您对已由Doctrine管理的现有对象进行更改时,会发生更新。许多人对此感到困惑,但在更新现有实体时无需致电persist()
,您只需要致电flush()
。例如:
// inserts a new entity into the database
$document = new Document();
$document->setName('My Document');
$em->persist($document);
$em->flush();
和
// retrieves entity from the database, makes a change, then updates the database
$document = $em->findOneByName('My Document');
$document->setFooCode('Salamanders');
$em->flush();
我鼓励你像Cerad建议的那样read the Doctrine documentation。请密切关注preUpdate
事件的以下陈述:
- PreUpdate是使用最严格的事件
- 此事件中绝不允许更改已更新实体的关联
- 刷新操作不再识别已传递实体的字段更改,使用传递给事件的计算更改集来修改原始字段值