Symfony2和Doctrine:如何为同一个id获取两个不同的对象?

时间:2013-02-08 10:29:20

标签: php symfony doctrine-orm symfony-2.1

我有这种情况:

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

等等。

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

如果我使用clone,显然,我复制了我的对象但是与他有关的对象没有被克隆。
我完全知道我可以覆盖魔术方法__clone()以便从A对象的角度分配 - B,C,D作为对象本身的克隆,但是我有很多对象(其中很多)因为Doctrine目的而包含在ArrayCollection中,我宁愿避免覆盖每个对象的克隆函数。

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

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

其中$aclass A

的实例

执行此操作后 - 当然是“错误的”,因为我怀疑该教条会将该对象标记为“alredy fetched”并返回其指针()* - 我只是打印ID我的两个对象具有spl_object_hash()函数,当然,它们也引用相同的对象ID,因此也指向同一个对象。

PS:

我不能使用doctrine detach()函数,因为我需要在此操作后使原始对象可用

问题

我该如何处理这种情况?正如你所看到的,我尝试了两种不同的方式,没有一种方式让我满意。

注意

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

(*)

  

在这种情况下,文章可以从实体经理访问两次,   但经过修改。教义2意识到这一点,并且只会永远   无论如何,您都可以访问ID为1234的文章的一个实例   你经常从EntityManager中检索它,甚至无论如何   你正在使用什么样的Query方法(find,Repository Finder或   DQL)。这称为“身份地图”模式,即Doctrine   保留每个实体的地图和每个PHP检索到的ID   请求并不断返回相同的实例。

这证实了我之前说过的话

2 个答案:

答案 0 :(得分: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:Original Obj:   000000006523 645c 000000004b1160d1 [] [] [2013-02-08 12:07:20]   app.DEBUG:复制对象:000000006523 66e3 000000004b1160d1 [] []

答案 1 :(得分:1)

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

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

WRT清算实体经理,它会分离所有管理实体,这可能会产生不良副作用。

HTH。