Symfony 保留对文档所做的更改,并遵循原则';s预更新生命周期事件

Symfony 保留对文档所做的更改,并遵循原则';s预更新生命周期事件,symfony,orm,doctrine-orm,lifecycle,Symfony,Orm,Doctrine Orm,Lifecycle,我有一个事件订阅服务器,它包含两个生命周期事件方法:prePersist和preUpdate。前一个正在按预期工作-我修改了文档,这些更改将在稍后检索文档时反映出来。但是,preUpdate未按预期工作。基本上是这样的: /** * Also update the foo code when the bar profile is updated. * @param LifecycleEventArgs $args */ public function preUpdate(Lifecycle

我有一个事件订阅服务器,它包含两个生命周期事件方法:prePersist和preUpdate。前一个正在按预期工作-我修改了文档,这些更改将在稍后检索文档时反映出来。但是,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');
    }
}
如果我创建了一个文档,并在perperpersist函数中将其fooCode设置为“placeholder”,那么当我稍后检索文档时,它的fooCode是“placeholder”。如果我随后更新它,并再次检索它,那么我希望它的foodcode是“蝾螈”。然而,它仍然是“占位符”。我甚至试着把
error\u log()
东西放在那里,它会把东西写到日志中,这样我就可以看到这个方法正在执行


$document->setFooCode()
之后,是否还有第二步要做,以使fooCode的新值保持不变?

您不能直接在
preUpdate
事件中修改字段,您必须修改它们的原始值。不允许更改关联。您必须执行以下操作:

$eventArgs->setNewValue('fooCode', 'Salamanders');
您声明“prePersist一个正在按预期工作-我修改了文档,这些更改将在稍后检索文档时反映出来。”

这让我相信您可能没有意识到持久化和更新之间的区别。在原则中,当您第一次创建对象时,将发生持久化。当您对已由条令管理的现有对象进行更改时,会发生更新。很多人对此感到困惑,但在更新现有实体时,不需要调用
persist()
,只需调用
flush()
。例如:

// inserts a new entity into the database
$document = new Document();
$document->setName('My Document');

$em->persist($document);
$em->flush();

我鼓励你喜欢Cerad的建议。密切注意
preUpdate
事件的以下语句:

  • PreUpdate是使用事件的最严格限制
  • 在此事件中,不允许更改已更新实体的关联
  • 刷新操作不再识别对传递的实体的字段所做的更改,请使用传递给事件的计算更改集修改基本字段值

请阅读详细说明和示例:。很多人在这件事上被绊倒了。我确实读过。。。但直到下面的答案解释了这一点,我才明白这意味着什么。实际上,我最终选择了中的解决方案,因为我无法让它识别我在对象上更改的属性名称。我知道这是旧的,但您的评论中有一部分不是100%正确的。如果使用ParamConverter,EntityManager不会跟踪注入控制器操作的实体,并且在刷新()时不会自动保存更改。因此,您需要首先持久化()该对象。感谢您提供的补充信息。这是新的行为吗?我知道我在2014年就回答了这个问题。从我开始使用Symfony开始,我就一直在那里工作,但我只做了一年半的Symfony开发人员。
// retrieves entity from the database, makes a change, then updates the database
$document = $em->findOneByName('My Document');
$document->setFooCode('Salamanders');

$em->flush();