PHP5 Tutorial - Magic Methods - __clone() method
Before I begin to explain the use of a __clone() method, lets try and understand what does object cloning mean.
To clone an object means to create a duplicate of an object. With regular variables $a = $b means that a new variable $a gets created that contains the value of $b. This means that 2 variables get created.
With objects $obj2 = $obj1 does not mean that a new object i.e. $obj2 gets created. When we execute $obj2 = $obj1, the reference of $obj1 is assigned to $obj2. This means that $obj1 and $obj2 point to the same memory space. Look at the diagram below.

Lets look at an example where only references are assigned to another object:
class Customer { private $name; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } } $c1 = new Customer(); $c1->setName("Sunil"); $c2 = $c1; //only reference or memory assigned to $c2 $c2->setName("Vishal"); echo $c1->getName()."\n"; echo $c2->getName()."\n";
Output:
Vishal
Vishal
In the above example, $c2 has the reference of $c1; therefore, when you set a new name in the $c2 object - $c1 object changes as well. Therefore, when an object is assigned as a reference; changes made to one object are also reflected in the other.
Therefore, to create a new $obj2 object we must clone an object to create a new one. To clone an PHP5 Object a special keyword i.e. clone is used. Example below:
$obj2 = clone $obj1;
After the above line is executed $obj2 with a new memory space is created with the data members having the same value as that of $obj1. This is also referred to as shallow copy.

The above technique works with a class having data members that are of intrinsic type i.e. int, boolean, string, float, etc.. However, this technique will not work with a class that has a data member which is an object of another class. In such a scenario, the cloned object continues to share the reference of the data member object of the class that was cloned.
So, how do we resolve this issue? Doing a regular shallow copy won’t help us. To allow aggregated objects (i.e. data members that are objects of another class) to also get cloned properly we need to use the concept of ‘deep copy‘ as opposed to ‘shallow copy‘. To implement a ‘deep copy‘ you should implement the magic method __clone().
You could also provide the implementation of __clone() magic method even when you don’t have an aggregated object. You would want to do this for providing necessary clean up operations, conversions or validations.
Lets explore a very simple example of cloning intrinsic data types:
class Customer { private $name; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function __clone() { $c = new Customer(); $c->setName($this->name); return $c; } } $c1 = new Customer(); $c1->setName("Sunil"); $c2 = clone $c1; //new object $c2 created $c2->setName("Vishal"); echo $c1->getName()."\n"; echo $c2->getName()."\n";
Output:
Sunil
Vishal
In the above example, observe the line where the statement $c2 = clone $c1 is executed. This is internally represented as $c2 = $c1.__clone(). However, you cannot explicitly call the __clone() method on an object as the __clone() is automatically called. Now that $c1 and $c2 are two individual objects, changes made to one object is not reflected in the other.
Cloning aggregate objects (i.e. data members that are objects of another class)
To clone a class having aggregated objects, you should perform ‘deep copy‘. Please refer to the example below:
class Order { private $order_id; private $customer; public function setOrderId($order_id) { $this->order_id = $order_id; } public function getOrderId() { return $this->order_id; } public function setCustomer(Customer $customer) { $this->customer = clone $customer; } public function getCustomer() { return $this->customer; } public function __clone() { $o = new Order(); $o->setOrderId($this->order_id); //force a copy of the same object to itself, otherwise //it takes the same instance. Seems like a bug to me $this->customer = clone $this->customer; $o->setCustomer($this->customer); return $o; } } class Customer { private $name; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function __clone() { $c = new Customer(); $c->setName($this->name); return $c; } } $c = new Customer(); $c->setName("Sunil"); $o1 = new Order(); $o1->setOrderId("OD0001"); $o1->setCustomer($c); $o2 = clone $o1; $o2->getCustomer()->setName("Vishal"); var_dump($c); var_dump($o1); var_dump($o2);
Output:
object(Customer)#1 (1) {
[”name:private”]=>
string(5) “Sunil”
}
object(Order)#2 (2) {
[”order_id:private”]=>
string(6) “OD0001″
[”customer:private”]=>
object(Customer)#3 (1) {
[”name:private”]=>
string(5) “Sunil”
}
}
object(Order)#4 (2) {
[”order_id:private”]=>
string(6) “OD0001″
[”customer:private”]=>
object(Customer)#6 (1) {
[”name:private”]=>
string(6) “Vishal”
}
}
In the above example both $o1 and $o2 have their own set of customer objects, therefore changes made to one object is not reflected in another. This example implements the concepts of ‘deep copy‘.
A special note on $this->customer = clone $this->customer; For some reason it is necessary to do this for proper working of aggregated cloning.
I hope this tutorial was helpful. Please feel free to leave behind any comments or questions that you might have.
Related Posts on PHP5 Tutorial - Object Oriented Programming (OOPS)
- PHP5 Tutorial - Learn to create a PHP5 Class
- PHP5 Tutorial - Learn to Create a PHP5 Class Object
- PHP5 Tutorial - Defining Attributes of a PHP5 Class
- PHP5 Tutorial - Defining Methods of a PHP5 Class
- PHP5 Tutorial - Creating a PHP5 Constructor __construct()
- PHP5 Tutorial OOPS - Creating a PHP5 Destructor __destruct()
- PHP5 Tutorial OOPS - PHP5 Class Access Specifiers - public, private and protected
- PHP5 Tutorial - Magic Methods - __toString() method
- PHP5 Tutorial - Magic Methods - __get() and __set()
- PHP5 Tutorial - Magic Methods - __isset() and __unset()
- PHP5 Tutorial - Magic Methods - __call() method
- PHP5 Tutorial - Magic Methods - __autoload() method
- PHP5 Tutorial - Magic Methods - __sleep() and __wakeup()
- PHP5 Tutorial - Magic Methods - __clone() method
Filed under: PHP, PHP Tutorials, PHP5 Magic Methods, PHP5 OOPS Tutorials
Thanks, helpful
Very good & interesting sum up. Thanks.
Very systematic Explanation than x & good luck
Really nice and easy explanation on the subject:-) In fact some of the best I ever read! U know the art of making it simple, man:-)
that’s what I needed, well done thanks!
You’ve overcomplicated this. First, if you just need to clone the object exactly then don’t define a __clone() method. It will be handled automatically by PHP. So you don’t have to define __clone() at all in the Customer class.
Second, you don’t have to make a copy of the object that you’re cloning. You can just operate on $this and PHP will take care of the rest. So rather that manually cloning the Order object in the __clone() method it can be just one line:
public function __clone {
$this->setCustomer($this->customer);
}
My reply to In8r:
public function __clone {
$this->setCustomer($this->customer);
}
As per your above statement, you are not copying the customer object - but only assigning the memory address of the existing customer object to the new object.
This means if the original customer object were to be deleted - the newly created pointer would become NULL.
That is the reason we need to clone.
Let me know if you need more clarifications.
Regards,
Suniil
Thanks, Its gud. But I cant understand the concept of Cloning aggregate objects at $o2 =clone $o1.Could u say everything in detail thru mail or this forum . pls say step by step wat will hapen at this stage $o2 =clone $o1
Hi Kirubakar,
When you do $o2 = $o1, then the memory of $o1 is assigned to $o2. This means that both the variables point to the same memory location. Therefore if you change data in memory - both the objects get to see it as they point to same memory location.
However, if this is your requirement - then its good. But in a real world scenario you would want to create another copy of $o1 so that if you make changes to $o1 - it does not get reflected to $o2.
Cloning means to allocate a new memory location to $o2 and copy the contents of $o1 into the newly allocated memory location.
Hope this explanation is clear.
Regards,
Suniil
Thank u for ur care, But I asked when this function
public function __clone() {
$o = new Order();
$o->setOrderId($this->order_id);
$this->customer = clone $this->customer;
$o->setCustomer($this->customer);
return $o;
}
will call, then what process will go here $o2->getCustomer()->setName(”Vishal”);
Plz explain
hi
In $o1->setCustomer($c); the object $o1 will it pont the memory of $c