Symfony2 and Doctrine: how to fetch two different

2019-02-22 07:32发布

I have this scenario:

  • Object A have some reference to other objects B,C,D
  • Object B have some reference to other objects A,F,G
  • Object C have some reference to other objects A,...

And so on.

In my code, I need to make a "copy" of an object (say A) for tmp reasons (no, I can't use a different structure, I need to have a copy of object).

If I use clone, obviously, I make a clone of my object but object related to him, aren't cloned.
I perfeclty know that I can override magic-method __clone() in order to assign to - from A object point of view - B,C,D as clone of objects themselves, but I have so many objects (and many of them are contained into ArrayCollection for Doctrine purpose) and I would prefer to avoid the override of each object's clone function.

Alternatively, I thought that I can refetch an object from doctrine to make a new one, in that way:

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

where $a is an instance of class A

After doing this operation - that of course is "wrong" because I suspect that doctrine will mark that object as "alredy fetched" and return its pointer()* - I simply print the ID of my two objects with spl_object_hash() function and, of course again, they refer to the same object ID, so to the same object.

PS.:

I can't use doctrine detach() function because i need to have the original object available after this operation

Question

How can I tackle this situation? As you can see, I've tryied two different ways and no one of them had satisfied me.

Note

I've tagged php also, because if someone could point me to a different solution, php-pure based, I'll take it into account also

(*)

In this case the Article is accessed from the entity manager twice, but modified in between. Doctrine 2 realizes this and will only ever give you access to one instance of the Article with ID 1234, no matter how often do you retrieve it from the EntityManager and even no matter what kind of Query method you are using (find, Repository Finder or DQL). This is called “Identity Map” pattern, which means Doctrine keeps a map of each entity and ids that have been retrieved per PHP request and keeps returning you the same instances.

That confirm what I've said previously

2条回答
闹够了就滚
2楼-- · 2019-02-22 08:23

Answer was less complex than I expected.

It seem to be sufficent call $this->entity_manager->clear(); that will clear this entity map and force it to reload from database into a brand new object!

$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));

this will print

[2013-02-08 12:07:20] app.DEBUG: Original Obj: 000000006523645c000000004b1160d1 [] [] [2013-02-08 12:07:20] app.DEBUG: Copied Obj: 00000000652366e3000000004b1160d1 [] []

查看更多
放荡不羁爱自由
3楼-- · 2019-02-22 08:33

So far as I know this is not a supported D2 behaviour out of the box, so I would say you'll need to implement the clone operation yourself.

Having said that, I'm also not 100% sure what'll happen if you serialize and then unserialize a D2 entity, this might do what you want (albeit in a rather unpleasant fashion). In addition you could, after fetching the entity initially, detach what you've received immediately and re-fetch the result again before any references to the 'live' copy have propagated outside of the original instantiation point (if the query's using the result cache this shouldn't carry too much of a penalty). Presumably this wouldn't be a tremendous problem however, as you're just working with the copy temporarily.

WRT to clearing the entity manager, it'll detach all managed entities, which may well have undesirable side-effects.

HTH.

查看更多
登录 后发表回答