Symfony2 and Doctrine: how to get two different objects for the same identifier?

I have a scenario like this:

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

Etc.

In my code I need to make a "copy" of the object (for example, A) for tmp reasons (no, I cannot use another structure, I need to have a copy of the object).

If I use clone , obviously I am creating a clone of my object, but the object associated with it is not cloned.
I know very well that I can redefine magic-method __clone() to assign - from the object point of view - B, C, D as cloning the objects themselves, but I have so many objects (and many of them are contained in ArrayCollection for the purpose of Doctrine) , and I would rather avoid overriding each cloning function of the object.

Alternatively, I thought I could restore an object from a doctrine to create a new one:

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

where $a is an instance of class A

After performing this operation, this is of course “wrong” because I suspect that the doctrine marks this object as “alredy fetched” and returns its pointer () * - I just print the identifier of my two objects using the spl_object_hash() function and Of course, again, they refer to the same object identifier, therefore, to the same object.

PS :.

I cannot use the doctrine detach() function because I need to have the source object accessible after this operation

Question

How can I solve this situation? As you can see, I tried two different ways, and none of them satisfied me.

Note

I also noted php, because if someone can point me to another solution based on php-pure, I will take it into account as well

(*)

In this case, the article gets access from the object manager twice, but changes between them. Doctrine 2 is aware of this and will only ever give you access to one copy of the article with the identifier 1234, no matter how often you extract it from the EntityManager and it doesn’t matter which query method you use (find, find repository or DQL). This is called the "Identity Map" template, which means "Doctrine" stores a map of each object and identifiers that were received on the PHP request and returns the same instances to you.

Confirm what I said earlier

+6
source share
2 answers

The answer was less complicated than I expected.

There seems to be a sufficient call to $this->entity_manager->clear(); which will clear this entity map and force it to reload from the database into a completely 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)); 

it will print

[2013-02-08 12:07:20] app.DEBUG: Original Obj: 000000006523 645c 000000004b1160d1 [] [] [2013-02-08 12:07:20] app.DEBUG: Copied Obj: 000000006523 66e3 000000004b1160d1 [] []

+3
source

As far as I know, this is not the supported behavior of D2 out of the box, so I would say that you need to implement the clone operation yourself.

Having said that, I'm also not 100% sure what will happen if you serialize and then non-serialize a D2 object, this can do what you want (albeit in a rather unpleasant way). In addition, after extracting the object, you can first separate what you received immediately and re-get the result again before any links to the live copy spread outside the starting point for creating the instance (if the query using the result cache doesn’t must bear too much punishment). Presumably, this would not be a huge problem, as you just work with the copy temporarily.

WRT to clean the entity manager, it will separate all managed objects that may have unwanted side effects.

NTN.

+1
source

All Articles