Copy a Doctrine object with all relationships

I want to copy a record with all its relationships.

I'm trying to:

$o = Doctrine::getTable('Table')->Find(x); $copy = $object->copy(); $relations = $o->getRelations(); foreach ($relations as $name => $relation) { $copy->$relation = $object->$relation->copy(); } $copy->save(); 

This code does not work, but I think it is on the way.

+3
php orm symfony1 doctrine
source share
5 answers

I could never get the deep copy function to work correctly.

I manually encoded a deep copy function for one of my models, such as

 public function copyAndSave () { $filters = array('id', 'created'); $survey = $this->copy(); $survey->Survey_Entries = new Doctrine_Collection("Survey_Model_Entry"); $survey->Assignment_Assignments = new Doctrine_Collection("Assignment_Model_Assignment"); $survey->Survey_Questions = new Doctrine_Collection("Survey_Model_Question"); $survey->save(); foreach ($this->Survey_Questions as $question) { $answers = $question->Survey_Answers; $newQuestion = $question->copy(); $newQuestion->survey_surveys_id = $survey->id; $newQuestion->save(); $newAnswers = new Doctrine_Collection("Survey_Model_Answer"); foreach($answers as $answer) { $answer = $answer->copy(); $answer->save(); $answer->survey_questions_id = $newQuestion->id; $newAnswers->add($answer); } $newQuestion->Survey_Answers = $newAnswers; $survey->Survey_Questions->add($newQuestion); } return $survey->save(); } 
+5
source share

You can read copy() here . It takes the optional parameter $deep :

$ deep
whether duplicate objects referenced by the relationship

So

 $copy = $object->copy(true); 

must do it.

+3
source share

Sorry if I revive this topic ...

I found myself searching for a solution lately, when I needed to copy a record and keep links to the original. A deep copy of $record->copy(true) copies the links, which is not suitable for me. This was my solution:

 $record = Doctrine_Core::getTable('Foo')->find(1); $copy = $record->copy(); foreach($record->getTable()->getRelations() as $relation) { if ($relation instanceof Doctrine_Relation_Association) { $ids = array(); foreach ($relation->fetchRelatedFor($record) as $r) { $ids[] = $r->getId(); } $copy->link($relation->getAlias(), $ids); } } if ($copy->isValid()) { $copy->save(); } 

Hope this helps :)

+2
source share

Here is how I did it, but some correction is required.

  $table = $entidade->getTable(); $relations = $table->getRelations(); foreach($relations as $relation => $data) { try { $entity->loadReference($relation); } catch(Exception $e) { die($e->getMessage()); } } 
0
source share

I am using Symfony1.4.1 and this is using Doctrine 1.2.1 (I think).

I am trying to make a function that did all this above when I found one that already exists.

Try this in any function and look at the results:

  $tmp=$this->toArray(TRUE); var_dump($tmp); $this->refreshRelated(); $tmp=$this->toArray(); var_dump($tmp); $tmp=$this->toArray(TRUE); var_dump($tmp); exit(); 

I am going to try two different things:

A / put $ this-> refreshRelated () in the constructor of all my model objects. B / write a function that takes an array representing the graph of the object I want to fill. Function call refereshRelatedGraph ($ objectGraphArray). With the correct structure of the array (having all the corresponding relationship names at each level), I could control which relationships are populated and which are not. One of them is to fill in only child, not parent, relationships. Another thing is that ERD / Schema / ObjectGraph has an element that "belongs" to more than one object (many of many, other special circumstances that I have), I could control which side of the relationship gets pre (not lazy) loaded.

0
source share

All Articles