PHP Object Assignment vs Cloning
Objects are abstract data in memory. A variable always holds a reference to this data in memory. Imagine that $foo = new Bar
creates an object instance of Bar
somewhere in memory, assigns it some id #42
, and $foo
now holds this #42
as reference to this object. Assigning this reference to other variables by reference or normally works the same as with any other values. Many variables can hold a copy of this reference, but all point to the same object.
clone
explicitly creates a copy of the object itself, not just of the reference that points to the object.
$foo = new Bar; // $foo holds a reference to an instance of Bar
$bar = $foo; // $bar holds a copy of the reference to the instance of Bar
$baz =& $foo; // $baz references the same reference to the instance of Bar as $foo
Just don't confuse "reference" as in =&
with "reference" as in object identifier.
$blarg = clone $foo; // the instance of Bar that $foo referenced was copied
// into a new instance of Bar and $blarg now holds a reference
// to that new instance
The difference between
$assigned = $instance
and
$assigned = clone $instance
is that in first case you assign a reference of already existing object and in second one you create a new object and assign it to the variable.
Moreover, when you use clone keyword you can use magic method __clone() which gives you better control on object cloning. From php manual:
Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.
From manual:
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
Let me give you a live example
$dateA = new \Datetime('2017-04-04');
$dateB = $dateA; // $dateB references exactly the same object as $dateA
$dateB->modify('+1 day');
var_dump($dateA->format('Y-m-d')); //string(10) "2017-04-05"
var_dump($dateB->format('Y-m-d')); //string(10) "2017-04-05"
// $dateA is still modified by the code above so it has 2017-04-05
$dateC = clone $dateA; // we clone $dateA so it's a new object
$dateC->modify('+1 day');
var_dump($dateA->format('Y-m-d')); // string(10) "2017-04-05"
var_dump($dateC->format('Y-m-d')); // string(10) "2017-04-06"
// side note for datetime I recommend using DatetimeImmutable instead of Datetime
EDIT: internal types
// create 2 integer variables $a and $b
$a = 1;
$b = 1;
// create a new $c variable and assign the *value* of $a to that variable
$c = $a;
// create a new $d variable and assign a reference to $b variable
$d = &$b;
// increment $b, $c and $d variables
$b++;
$c++;
$d++;
echo $a; // 1
echo $b; // 3
echo $c; // 2
echo $d; // 3
because $d references $b when we increment its value it'll also change the value of $b.
The difference between internal objects like strings, int, float etc. is that they are passed by value and objects are passed by default via reference
Notice: You cannot use clone with internal objects.