Object cloning refers to the creation of an exact copy of an object. It creates a new instance of the class of the current object and initializes all its fields with exactly the contents of the corresponding fields of this object.
An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). $copy_of_object = clone $object; When an object is cloned, PHP will perform a shallow copy of all of the object's properties. Any properties that are references to other variables will remain references.
The clone() method saves the extra processing task for creating the exact copy of an object. If we perform it by using the new keyword, it will take a lot of processing to be performed, so we can use object cloning.
Object cloning is the act of making a copy of an object. As Cody pointed out, cloning in PHP is done by making a shallow copy of the object. This means that internal objects of the cloned object will not be cloned, unless you explicitly instruct the object to clone these internal objects too, by defining the magic method __clone()
.
If you don't utilize the __clone
method, the internal objects of the new object will be references to the same objecs in memory as the internal objects of the original object that was cloned.
Consider these examples:
// in this exampe the internal member $_internalObject of both objects
// reference the same instance of stdClass in memory.
class CloneableClass
{
private $_internalObject;
public function __construct()
{
// instantiate the internal member
$this->_internalObject = new stdClass();
}
}
$classA = new CloneableClass();
$classB = clone $classA;
// in this exampe the internal member $_internalObject of both objects
// DON'T reference the same instance of stdClass in memory, but are inividual instances
class CloneableClass
{
private $_internalObject;
public function __construct()
{
// instantiate the internal member
$this->_internalObject = new stdClass();
}
// on clone, make a deep copy of this object by cloning internal member;
public function __clone()
{
$this->_internalObject = clone $this->_internalObject;
}
}
$classA = new CloneableClass();
$classB = clone $classA;
Use cases for cloning would for instance be a case where you don't want outside objects to mess with the internal state of an object.
Let's say you have a class User with a internal object Address.
class Address
{
private $_street;
private $_streetIndex;
private $_city;
// etc...
public function __construct( $street, $streetIndex, $city /* etc.. */ )
{
/* assign to internal values */
}
}
class User
{
// will hold instance of Address
private $_address;
public function __construct()
{
$this->_address = new Address( 'somestreet', '1', 'somecity' /* etc */ );
}
public function getAddress()
{
return clone $this->_address;
}
}
For arguments sake, let's say you don't want outside objects to mess with the internal Address of User objects, but you do want to be able to give them a copy of the Address object. The above example illustrates this. The getAddress
method returns a clone of the address object to calling objects. This means that if the calling object alters the Address object, the internal Address of User will not change. If you didn't give a clone, then the outside object would be able to alter the internal Address of User, because a reference is given by default, not a clone.
Hope this all makes some sense.
PS.:
Be aware though, that if Address would also have internal objects, you would have to make sure Address makes a deep copy of itself on cloning (as per my second example of this post) by defining __clone()
in Address. Otherwise you will get headaches of trying to figure out why your data is screwed.
Cloning is used to create a genuine copy of an object. Assigning an object to another variable does not create a copy - rather, it creates a reference to the same memory location as the object:
<?php
$o= new stdclass;
$o->a= 'b';
$o->b= 'c';
$o2= $o;
$o2->a= 'd';
var_dump($o);
var_dump($o2);
$o3= clone $o;
$o3->a= 'e';
var_dump($o);
var_dump($o3);
?>
This example code will output the following:
object(stdClass)#1 (2) {
["a"]=>
string(1) "d"
["b"]=>
string(1) "c"
}
object(stdClass)#1 (2) {
["a"]=>
string(1) "d"
["b"]=>
string(1) "c"
}
object(stdClass)#1 (2) {
["a"]=>
string(1) "d"
["b"]=>
string(1) "c"
}
object(stdClass)#2 (2) {
["a"]=>
string(1) "e"
["b"]=>
string(1) "c"
}
Object Cloning, in terms of PHP 5, is what is known as a "shallow copy". It then calls the __clone() method on the object being cloned.
If you need a deep clone - that is, clones of the child objects and clones of the grandchild objects - you can either overwrite __clone
in each of the classes, or simply serialize+unserialize the object:
function deepClone($object)
{
return unserialize(serialize($object));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With