doctrine持久化实体在entityManager-> persist和unitOfWork-> persist之间切换

时间:2015-04-12 20:43:42

标签: php entity-framework symfony doctrine-orm unit-of-work

在我的symfony2 / doctrine2应用程序中,我有一个奇怪的情况,当持久化修改后的实体时,更改不会刷新到数据库,我无法理解为什么。

以下是我的代码:

$date = $subscription->getPaymentValidUntil()->format('d/m/Y');
$period = $payment->getDetail('period');
$validDate = $subscription->getPaymentValidUntil()
    ->add(new\DateInterval($period == Subscription::MONTH ? 'P1M' : 'P1Y'))
;

$subscription->setPaymentValidUntil($validDate);
$this->em->persist($subscription);

exit(var_dump(array(
    $date,
    $this->em->getUnitOfWork()->getScheduledEntityUpdates(),
    $subscription->getPaymentValidUntil(),
)));

$this->em->flush();

vardump的输出如下:

array (size=3)
  0 => string '12/05/2015' (length=10)
  1 => 
    array (size=0)
      empty
  2 => 
    object(DateTime)[2295]
      public 'date' => string '2015-06-12 18:52:37' (length=19)
      public 'timezone_type' => int 3
      public 'timezone' => string 'Europe/Paris' (length=12)

如果我在vardump之前刷新或删除vardump,事实上,我的数据库中的日期值不会改变。为什么?

正如您所看到的,我在此日期值中添加了一个月,它反映在实体中,但未安排更新。我该如何解决这个问题?

编辑:我已经深入研究了实体管理器持久化函数,并且我发现当在Doctrine \ ORM \ EntityManager :: persist中转储实体时,日期很好,但是当它在Doctrine \ ORM \ UnitOfWork中转储时::坚持,日期已经以某种方式重置为原来的日期:

Doctrine\ORM\EntityManager::persist:转储更新后的实体

public function persist($entity)
{
    if ( ! is_object($entity)) {
        throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()' , $entity);
    }

    $this->errorIfClosed();

    if ($entity instanceof Subscription) exit(var_dump($entity));

    $this->unitOfWork->persist($entity);
}

Doctrine \ ORM \ UnitOfWork :: persist:转储未修改的实体:为什么?

private function doPersist($entity, array &$visited)
{
    if ($entity instanceof Subscription) exit(var_dump($entity));

        $oid = spl_object_hash($entity);

        if (isset($visited[$oid])) {
            return; // Prevent infinite recursion
        }
}

1 个答案:

答案 0 :(得分:4)

DateTime毕竟是对象,并且总是通过引用传递。所以,我强烈建议您像这样编辑代码:

$period = $payment->getDetail('period');
$validDate = clone $subscription->getPaymentValidUntil();
$validDate->add(new \DateInterval($period == Subscription::MONTH ? 'P1M' : 'P1Y'));
$subscription->setPaymentValidUntil($validDate);
$this->em->persist($subscription);
$this->em->flush();

这样,您可以确保将另一个对象传递给实体,并避免EntityManager中的任何细微错误。