6

我有这种情况:

  • 对象 A 对其他对象 B、C、D 有一些引用
  • 对象 B 对其他对象 A、F、G 有一些引用
  • 对象 C 对其他对象 A 有一些引用,...

等等。

在我的代码中,出于 tmp 的原因,我需要制作一个对象(比如 A)的“副本”(不,我不能使用不同的结构,我需要一个对象的副本)。

如果我使用clone,显然,我会克隆我的对象,但与他相关的对象不会被克隆。
我完全知道我可以重写魔术方法__clone(),以便分配给 - 从 A 对象的角度来看 - B、C、D 作为对象本身的克隆,但是我有很多对象(其中许多对象包含在ArrayCollectionDoctrine 中目的),我宁愿避免覆盖每个对象的克隆函数。

或者,我认为我可以通过这种方式从教义中重新获取一个对象来制作一个新对象:

$aCopy = $this->entity_manager
                       ->getRepository('MyBundle:A')
                       ->find($a->getId());

$a的一个实例在哪里class A

完成此操作后——这当然是“错误的”,因为我怀疑教义会将该对象标记为“已获取”并返回其指针()*——我只需使用spl_object_hash()函数打印我的两个对象的 ID,当然还有,它们引用相同的对象 ID,因此指向相同的对象。

PS:

我不能使用教义detach()功能,因为我需要在此操作后使原始对象可用

问题

我该如何解决这种情况?如您所见,我尝试了两种不同的方法,但没有一种让我满意。

笔记

我也标记了 php,因为如果有人可以向我指出不同的解决方案,基于 php-pure,我也会考虑它

(*)

在这种情况下,从实体管理器访问文章两次,但在两者之间进行了修改。Doctrine 2 意识到了这一点,并且只会让您访问 ID 为 1234 的文章的一个实例,无论您多久从 EntityManager 检索它,甚至无论您使用哪种查询方法(查找、存储库查找器或DQL)。这称为“身份映射”模式,这意味着 Doctrine 保留每个 PHP 请求检索到的每个实体和 id 的映射,并不断返回相同的实例。

这证实了我之前所说的

4

2 回答 2

3

答案没有我预期的那么复杂。

似乎足够的调用$this->entity_manager->clear();将清除此实体映射并强制它从数据库重新加载到一个全新的对象中!

$this->entity_manager->clear();
$aCopy = $this->entity_manager
                       ->getRepository('MyBundle:A')
                       ->find($a->getId());
            $this->logger->debug('Original Obj: '.spl_object_hash($a));
            $this->logger->debug('Copied Obj:      '.spl_object_hash($aCopy));

这将打印

[2013-02-08 12:07:20] app.DEBUG:原始 Obj:000000006523 645c 000000004b1160d1 [] [] [2013-02-08 12:07:20] app.DEBUG:复制的 Obj:000000006500046e3 00001 ] []

于 2013-02-08T11:14:48.120 回答
1

据我所知,这不是开箱即用的受支持的 D2 行为,所以我想说您需要自己实现克隆操作。

话虽如此,我也不是 100% 确定如果你序列化然后反序列化 D2 实体会发生什么,这可能会做你想要的(尽管以一种相当不愉快的方式)。此外,您可以在最初获取实体之后,分离您立即收到的内容并在对“实时”副本的任何引用传播到原始实例化点之外之前再次重新获取结果(如果查询使用结果缓存这不应该带来太多的惩罚)。但是,大概这不会是一个大问题,因为您只是暂时使用副本。

WRT 清除实体管理器,它将分离所有托管实体,这很可能会产生不良的副作用。

HTH。

于 2013-02-08T11:17:05.163 回答