一组实体未更新(Symfony2& Doctrine)

时间:2015-05-18 11:36:07

标签: php symfony doctrine-orm

我对此代码有疑问:

$elements = $em
    ->getRepository('AppBundle:MyElementsEntity')
    ->findByLinkType($linkType); // This returns SEVEN elements

foreach ($elements as $e) {
    $beginDate = $e->getBeginDate();
    $beginDate->setTime($begin->format('H'), $begin->format('i'));
    $endDate = $e->getEndDate();
    $endDate->setTime($end->format('H'), $end->format('i'));

    $e->setEndDate($endDate);
    $e->setBeginDate($beginDate);

    $em->persist($e);
    $em->flush();
}

如您所见,它从数据库中获取一些元素,从beginDate和endDate字段更改时间($ begin和$ end是DateTime对象),并尝试更新数据库。

代码不会抛出任何异常,但它不起作用。当我查看Symfony2的日志(app / logs / dev.log)时,会有SQL语句来获取数据,更改会话等,但是没有任何更新语句。

我还有另一个功能,每次只更新一个元素,这是正常的。

我做错了什么?为什么我可以批量更新以前选择的元素?我错过了一些重要的东西?

**更新**

我已经对代码进行了一些修改,但它仍然没有将实体更新到数据库中:

  • 我已删除了$em->persist($e)来电。
  • 我已将$em->flush()电话移至foreach圈外。
  • 我已删除了交易代码(beginTransaction()commit()rollback()来电)

但问题仍然存在:Doctrine没有向服务器发送任何UPDATE语句(仅供参考,是Oracle 11g)。

2 个答案:

答案 0 :(得分:0)

你对循环的意图是什么?我不接缝做任何事情......如果实体没有改变(脏),Doctrine将不会执行更新查询。

$begin = $e->getBeginDate();
// $begin = 2015-05-18 14:02:00
// $begin->format('H') // will return 14
// $begin->format('i') // will return 02 

$begin->setTime($begin->format('H'), $begin->format('i'));
// $begin is still 2015-05-18 14:02:00

为什么你的循环没有做任何事情:

{{1}}

答案 1 :(得分:0)

感谢所有人的帮助。最后,我发现了问题。

问题在于Doctrine查看实体是否脏的方式。他只查找标量字段(字符串,数字等)中的更改,但不查找作为对象的字段(另一个实体, DateTime对象等)。

在上面的代码片段中,我只修改了DateTime对象($e->beginDate$e->endDate)的内容,但没有创建新对象。这样,Doctrine没有注意到实体的变化。避免这种情况的解决方案非常简单:

foreach ($elements as $e) {
    $beginDate = clone $e->getBeginDate();
    $beginDate->setTime($begin->format('H'), $begin->format('i'));
    $endDate = clone $e->getEndDate();
    $endDate->setTime($end->format('H'), $end->format('i'));

    $e->setEndDate($endDate);
    $e->setBeginDate($beginDate);

    $em->flush();
}

初始化clone$beginDate临时变量时请注意$endDate关键字:它们不是对$e->beginDate$e->endDate成员的引用,而是副本他们然后,当您再次将新值分配给实体时,对象是新的,并且Doctrine现在知道这些实体是脏的。