Copying objects in PHP 5 using clone

In PHP 4 object variables were simple. Assigning one object to another worked exactly as you'd expect.

$object1->title = "Title One";
$object2 = $object1;
$object2->title = "Title Two";
print $object1->title; // returns "Title One"

You could make a copy of the original, and modify your copy with full assurance that your original would remain untouched.

That changed in PHP 5. Now when you assign an object to a new variable. The 2 variables remain inextricably linked.

$object1->title = "Title One";
$object2 = $object1;
$object2->title = "Title Two";
print $object1->title; // returns "Title Two"

In order to create an actual copy and not simply a reference to an existing object, PHP introduced the clone keyword.

$object1->title = "Title One";
$object2 = clone $object1;
$object2->title = "Title Two";
print $object1->title; // returns "Title One"

Now you can modify your newly cloned object to your heart's delight, while keeping intact your original.

For more information about Objects, References and Cloning in PHP read these pages.

Today I came across a less intuitive example of this object assignment gotcha. It involves storing objects statically inside a function. In this example, you might expect to grab an object using the load_object() function and make changes to the returned object without affecting the static cache inside that function. You'd be wrong.

function load_object($id) {
  static $nodes = array();
 
  if (empty($nodes[$id])) {
    $node = new stdClass;
    $node->title = "My Title";
 
    $nodes[$id] = $node;
  }
 
  return $nodes[$id]; // returned object simply points to $nodes[$id] instead of creating a copy
}
 
$obj = load_object(1);
 
print $obj->title; // returns "My Title"
 
$obj->title = "My Changed Title"; // Changing the title in this object also changes the original $nodes[1] object
 
// Load the statically cached $nodes[1] object into a new variable
$obj2 = load_object(1);
 
print $obj2->title; // returns "My Changed Title"

In order to keep your static cache objects preserved, you'll need to again use the clone keyword.

function load_object($id) {
  static $nodes = array();
 
  if (empty($nodes[$id])) {
    $node = new stdClass;
    $node->title = "My Title";
 
    $nodes[$id] = $node;
  }
 
  return clone $nodes[$id]; // returned object is an unlinked copy instead of a reference to the original
}
 
$obj = load_object(1);
 
print $obj->title; // returns "My Title"
 
$obj->title = "My Changed Title"; // Changing the title in this object also changes the original $nodes[1] object
 
// Load the statically cached $nodes[1] object into a new variable
$obj2 = load_object(1);
 
print $obj2->title; // returns "My Changed Title"
Tags:

Comments

copy object

this example is very simple and useful

Thank you!

Thank you!

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <strike> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <bash>, <css>, <drupal5>, <drupal6>, <javascript>, <mysql>, <php>, <python>, <ruby>. The supported tag styles are: <foo>, [foo].
  • You can use Markdown syntax to format and style the text. Also see Markdown Extra for tables, footnotes, and more.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.