Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep clone Doctrine entity with related entities

I have created an entity A with OneToMany relation to B, which have relation OneToMany to C.

I have to clone this A entity and set it in database with new id. Also all deep relations should be cloned with new ids too.

What have I tried is to set A id to null:

$A = clone $A_original; $A->setId(null); $em->persist($A); 

It creates new record in A table, but does not in B and C.

What should I do to make a full copy of A entity ?

like image 342
hsz Avatar asked Jan 04 '13 13:01

hsz


2 Answers

You have to implement a __clone() method in your entities that sets the id to null and clones the relations if desired. Because if you keep the id in the related object it assumes that your new entity A has a relation to the existing entities B and C.

Clone-method for A:

public function __clone() {     if ($this->id) {         $this->setId(null);         $this->B = clone $this->B;         $this->C = clone $this->C;     } } 

Clone-method for B and C:

public function __clone() {     if ($this->id) {         $this->setId(null);     } } 

https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/Nu2rayrDkgQ

https://doctrine-orm.readthedocs.org/en/latest/cookbook/implementing-wakeup-or-clone.html

Based on the comment of coder4show a clone-method for a OneToMany relationship on A where $this->M is OneToMany and therefore an ArrayCollection:

public function __clone() {     if ($this->id) {         $this->setId(null);          // cloning the relation M which is a OneToMany         $mClone = new ArrayCollection();         foreach ($this->M as $item) {             $itemClone = clone $item;             $itemClone->setA($this);             $mClone->add($itemClone);         }         $this->M = $mClone;     } } 
like image 195
flec Avatar answered Oct 02 '22 15:10

flec


There is also a module that will do this called DeepCopy:

https://github.com/myclabs/DeepCopy

$deepCopy = new DeepCopy(); $myCopy   = $deepCopy->copy($myObject); 

You can also add filters to customize the copy process.

like image 27
Onshop Avatar answered Oct 02 '22 14:10

Onshop