ÄúµÄλÖãºÑ°ÃÎÍøÊ×Ò³£¾±à³ÌÀÖÔ°£¾PHP ±à³Ì£¾PHP 5 Power programming
Team LiB
Previous Section Next Section

3.8. Cloning Objects

When creating an object (using the new keyword), the returned value is a handle to an object or, in other words, the id number of the object. This is unlike PHP 4, where the value was the object itself. This doesn't mean that the syntax for calling methods or accessing properties has changed, but the copying semantics of objects have changed.

Consider the following code:

class MyClass {
    public $var = 1;
}

$obj1 = new MyClass();
$obj2 = $obj1;
$obj2->var = 2;
print $obj1->var;

In PHP 4, this code would have printed 1, because $obj2 is assigned the object value of $obj1, therefore creating a copy, leaving $obj1 unchanged. However, in PHP 5, because $obj1 is an object handle (its id number), what is copied to $obj2 is the handle. So, when changing $obj2, you actually change the same object $obj1 is referencing. Running this code snippet, therefore, results in 2 being printed.

Sometimes, though, you really do want to create a copy of the object. How can you achieve that? The solution is the language construct clone. This built-in operator automatically creates a new instance of the object with its own copy of the properties. The property values are copied as is. In addition, you may define a __clone() method that is called on the newly created object to perform any final manipulation.

Note

References are copied as references, and don't perform a deep copy. This means that if one of your properties points at another variable by reference (after it was assigned by reference), after the automatic cloning, the cloned object will point at the same variable.


Changing the $obj2 = $obj1; line in the previous example to $obj2 = clone $obj1; will assign $obj2 a handle to a new copy of $obj1, resulting in 1 being printed out.

As previously mentioned, for any of your classes, you may implement a __clone() method. After the new (cloned) object is created, your __clone() method is called and the cloned object is accessible using the $this variable.

The following is an example of a typical situation where you might want to implement the __clone() method. Say that you have an object that holds a resource such as a file handle. You may want the new object to not point at the same file handle, but to open a new one itself so that it has its own private copy:

class MyFile {
    function setFileName($file_name)
    {
        $this->file_name = $file_name;
    }

    function openFileForReading()
    {
      $this->file_handle = fopen($this->file_name, "r");
    }

    function __clone()
    {
        if ($this->file_handle) {
            $this->file_handle = fopen($this->file_name, "r");
        }
    }

    private $file_name;
    private $file_handle = NULL;
}

Although this code is only partially written, you can see how you can control the cloning process. In this code snippet, $file_name is copied as is from the original object, but if the original object has an open file handle (which was copied to the cloned object), the new copy of the object will create its own copy of the file handle by opening the file by itself.

    Team LiB
    Previous Section Next Section