PHP 5 Magic – _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:
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$c1 = new Customer();
$c1->setName(“Timir”);
$c2 = $c1; //only reference or memory assigned to $c2
$c2->setName(“Ankur”);
echo $c1->getName().”\n”;
echo $c2->getName().”\n”;
Output:
Ankur
Ankur
Therefore, to create a new $obj2 object we must clone an object to create a new one. To clone an PHP Object a special keyword i.e. clone is used. Example below:
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.

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:
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(“Timir”);
$c2 = clone $c1; //new object $c2 created
$c2->setName(“Ankur”);
echo $c1->getName().”\n”;
echo $c2->getName().”\n”;
Output:
Timir
Ankur
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:
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(“Timir”);
$o1 = new Order();
$o1->setOrderId(“OD0001″);
$o1->setCustomer($c);
$o2 = clone $o1;
$o2->getCustomer()->setName(“Ankur”);
var_dump($c);
var_dump($o1);
var_dump($o2);
Output:
object(Customer)#1 (1) {
[â€name:privateâ€]=>
string(5) “Timirâ€
}
object(Order)#2 (2) {
[â€order_id:privateâ€]=>
string(6) “OD0001″
[â€customer:privateâ€]=>
object(Customer)#3 (1) {
[â€name:privateâ€]=>
string(5) “Timirâ€
}
}
object(Order)#4 (2) {
[â€order_id:privateâ€]=>
string(6) “OD0001″
[â€customer:privateâ€]=>
object(Customer)#6 (1) {
[â€name:privateâ€]=>
string(6) “Ankurâ€
}
}
“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 Post is very helpful to you.If you have any questions or suggestions then please comment on this post.
-
http://www.customerservicehelper.com/ Dan Waldron
-
http://www.customerservicehelper.com Dan Waldron




