Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 and Doctrine: how to fetch two different object for the same id?

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

like image 481
DonCallisto Avatar asked Feb 08 '13 10:02

DonCallisto


1 Answers

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 [] []

like image 103
DonCallisto Avatar answered Oct 22 '22 07:10

DonCallisto