学说持久化实体在 entityManager->persist 和 unitOfWork->persist 之间改变
doctrine persisted entity changed between entityManager->persist and unitOfWork->persist
在我的 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
}
}
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 中的任何细微错误。
在我的 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
}
}
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 中的任何细微错误。