使用Doctrine的PreUpdate生命周期事件保留对文档所做的更改

时间:2014-12-31 00:50:40

标签: symfony orm doctrine-orm lifecycle

我有一个包含两个生命周期事件方法的事件订阅者: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的新值保持不变?

1 个答案:

答案 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是使用最严格的事件
  •   
  • 此事件中绝不允许更改已更新实体的关联
  •   
  • 刷新操作不再识别已传递​​实体的字段更改,使用传递给事件的计算更改集来修改原始字段值
  •