Question

What is the best way to create a clone of a complex PHP object that includes many references to itself, so that the new object's references point to its own methods and properties, not those of the original object?

I understand from the manual that $new_object = clone $old_object; creates a shallow copy that keeps references where they are. So presumably $new_object's references will point to methods on the old object?

A comment on that manual page suggests that $new_object = unserialize(serialize($old_object)); is a way to create a deep copy. Sounds promising, I'm not sure exactly what this approach would mean for my case: whether references are converted to point to the clone, or made absolute, or something else, and if does do what I want, whether it's the best way.

I'd like to know if there's an established, standard way to do this.

(Note: the object in question is a Drupal Views object, but this question is about PHP objects in general: the only important features of this object are, that it is huge, and contains many references to itself that recurse if you try to navigate the whole tree.)

Was it helpful?

Solution

A simple test will reveal what happens:

$old = new stdClass();
$old->foo = 'bar';
$old->baz = &$old;

print_r($old);

$new = unserialize(serialize($old));

$new->foo = 'new';

print_r($new);
print_r($new->baz->foo);

This code shows that the self-ref now points to the clone. http://codepad.org/dSnZ5I10

OTHER TIPS

Here's some basic testing and results. Not a complete answer but hopefully useful. Also please correct me if my approach is wrong. Assume $view is an object that already contains lots of self-reference and loads of data:

      $view->somedata = "This is the default";
      $view->selfreference =& $view->somedata;

      $new = clone $view;
      $new2 = unserialize(serialize($view));

      $view->somedata = "This is view";
      $new->somedata = "This is new";
      $new2->somedata = "This is new2";

      echo("$view: ".$view->selfreference);
      echo("$new: ".$new->selfreference);
      echo("$new2: ".$new2->selfreference);

Results:

'$view: This is new'
'$new: This is new'
'$new2: This is new2'

So at first investigation, it looks like the shallow clone with clone points the self-references to the original, and the unserialize(serialize()) approach maintains the reference and points it to the new object.

So it looks like unserialize(serialize()) works and doesn't crash out with an infinite loop or excessive recursion. I'd like to hear people's thoughts on whether this is a best, standard and/or accepted approach.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top