gpt4 book ai didi

php - onFlush 中的计划实体是不同的实例

转载 作者:可可西里 更新时间:2023-11-01 13:29:40 26 4
gpt4 key购买 nike

我在 onFlush 事件中使用的 \Doctrine\ORM\UnitOfWork::getScheduledEntityDeletions 有一个奇怪的问题

foreach ($unitOfWork->getScheduledEntityDeletions() as $entity) {
if ($entity instanceof PollVote) {
$arr = $entity->getAnswer()->getVotes()->toArray();

dump($arr);
dump($entity);

dump(in_array($entity, $arr, true));
dump(in_array($entity, $arr));
}
}

结果如下:

dump() output

因此我们看到该对象指向与原始实例不同的实例,因此 in_array 在使用棒比较时不再产生预期的结果(又名 === ).此外,\DateTime 对象指向不同的实例。

我找到的唯一可能的解释如下(source):

Whenever you fetch an object from the database Doctrine will keep a copy of all the properties and associations inside the UnitOfWork. Because variables in the PHP language are subject to “copy-on-write” the memory usage of a PHP request that only reads objects from the database is the same as if Doctrine did not keep this variable copy. Only if you start changing variables PHP will create new variables internally that consume new memory.

但是,我没有做任何更改(甚至 created 字段也保持原样)。在实体上执行的唯一操作是:

  1. \Doctrine\ORM\EntityRepository::findBy(从数据库获取)
  2. \Doctrine\Common\Persistence\ObjectManager::remove(删除计划)
  3. $em->flush();(触发与DB同步)

这让我认为(我可能是错的)Doctrine 的更改跟踪方法与我遇到的问题无关。这让我想到了以下问题:

  • 是什么原因造成的?
  • 如何可靠地检查计划删除的实体是否在集合内(\Doctrine\Common\Collections\Collection::contains 使用 in_array 进行严格比较)或集合中的哪些项目计划删除?

最佳答案

问题是,当您告诉 doctrine 删除实体时,它会从身份映射 (here) 中删除:

<?php

public function scheduleForDelete($entity)
{
$oid = spl_object_hash($entity);

// ....

$this->removeFromIdentityMap($entity);

// ...

if ( ! isset($this->entityDeletions[$oid])) {
$this->entityDeletions[$oid] = $entity;
$this->entityStates[$oid] = self::STATE_REMOVED;
}
}

当您执行 $entity->getAnswer()->getVotes() 时,它会执行以下操作:

  1. 从数据库中加载所有选票
  2. 对于每一张选票,检查它是否在身份映射中,使用旧的
  3. 如果不在identity map中,创建新对象

在删除实体之前尝试调用 $entity->getAnswer()->getVotes()。如果问题消失了,那么我是对的。当然,我不会建议将此 hack 作为解决方案,只是为了确保我们了解引擎盖下发生的事情。

UPD 而不是 $entity->getAnswer()->getVotes() 您可能应该为所有投票执行 foreach,因为延迟加载。如果你只是调用 $entity->getAnswer()->getVotes(),Doctrine 可能不会做任何事情,并且只会在你开始遍历它们时加载它们。

关于php - onFlush 中的计划实体是不同的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41102378/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com