I have an object oriented parent child of a PHP tree that I want to clone. The hard part is that access to the tree is not always through the root, but sometimes through a child of the root, for example:
[Root] -- [Element1] START CLONE -- [Element3] -- [Element4] -- [Element2] -- [Element5]
So what I want to do is clone the whole tree by calling $new = clone $element1;
The __clone () method indicates that each of the children must also be cloned, and if the situation * is illustrated, the parent must also be cloned.
* Root is explicitly set as the parent in element 1, so the system can identify this situation and do something with it.
The problem is that, starting with the clone operation from Element1, Root must also be cloned. The clone procedure for Root requires all children to be cloned, and so the clone operation for Element1 is called again, which then repeats the same clone procedure, creating an endless loop.
In addition, Root will not contain the first clone of Element1, but it will create its own clone to be added as a child of. Element1 will have Root as the parent, but Root will not have the same Element1 as the child.
I hope I have posed the problem explicitly and that someone can help me find a solution.
EDIT:
Final decision:
/** * The $replace and $with arguments allow a custom cloning procedure. Instead of * being cloned, the original child $replace will be replaced by $with. */ public function duplicate($replace = null, $with = null) { // Basic cloning $clone = clone $this; // If parent is set if(isset($this->parent)) { // Clone parent, replace this element by its clone $parentClone = $this->parent->duplicate($this, $clone); $clone->parent = $parentClone; } // Remove all children in the clone $clone->clear(); // Add cloned children from original to clone foreach($this->getChildren() as $child) { if($child === $replace) // If cloning was initiated from this child, replace with given clone $childClone = $with; else // Else duplicate child normally $childClone = $child->duplicate(); // Add cloned child to this clone $clone->add($childClone); } return $clone; }