Is it that in PHP, copying the value of variable Y into variable X is done this way $copy = clone $original
and if so, why won’t it be just $copy = $original
instead?
What have you tried?
This is one of those lovely cases where trying it can be misleading.
copy and clone essentially do the same thing and will do a copy of the references to an abject. The difference comes in you can break the reference in a clone IF you handle it within the object you clone - it doesn’t happen automagically like it does in other languages like C# and python.
Quick and dirty
<?php
class MyClass {
public $amount;
}
// Create an object with a reference
$value = 5;
$obj = new MyClass();
$obj->amount = &$value;
// Clone the object
$clone = clone $obj;
$copy = $obj;
// Change the value in the original object
$obj->amount = 6;
// The value for amount has changed in both...
print_r($clone);
print_r($copy);
// Output
// MyClass Object ( [amount] => 6 ) MyClass Object ( [amount] => 6 )
?>
But if you handle the cloning action, the results will change
<?php
class MyClass {
public $amount;
public function __clone() {
$value = $this->amount;
unset($this->amount); // Unset breaks references
$this->amount = $value;
}
}
// Create an object with a reference
$value = 5;
$obj = new MyClass();
$obj->amount = &$value;
// Clone the object
$clone = clone $obj;
$copy = $obj;
// Change the value in the original object
$obj->amount = 6;
// The value is changed in copy but not in clone
print_r($copy);
print_r($clone);
// Output
// MyClass Object ( [amount] => 6 ) MyClass Object ( [amount] => 5 )
?>
The short answer is it depends what you are copying. If the value is an object then assigning the value to another variable will just copy a reference. In all other cases (numbers, strings, arrays) it will make a copy.
eg:
$a = 1;
$b = $a;
$b = 2;
var_dump($a,$b);
Outputs
int(1)
int(2)
$a = array();
$a['val'] = 1;
$b = $a;
$b['val'] = 2;
var_dump($a,$b);
Output
array(1) {
["val"]=>
int(1)
}
array(1) {
["val"]=>
int(2)
}
So in both of these cases the $b variable is it’s own thing and you can change it without affecting $a.
But with an object:
$a = new \StdClass();
$a->val = 1;
$b = $a;
$b->val=2;
var_dump($a,$b);
Output:
object(stdClass)#718 (1) {
["val"]=>
int(2)
}
object(stdClass)#718 (1) {
["val"]=>
int(2)
}
Both variables now have the same value, because $b is just a reference to $a. Also changing $a will affect $b.
This is where clone comes in:
$a = new \StdClass();
$a->val = 1;
$b = clone $a;
$b->val=2;
var_dump($a,$b);
Output:
object(stdClass)#805 (1) {
["val"]=>
int(1)
}
object(stdClass)#717 (1) {
["val"]=>
int(2)
}
Now $b is not a reference to $a, changing one does not change the other.
Also, clone can only be used on objects.
Hello Gandalf,
I didn’t try any of these codes before asking but after reading your reply I tried:
<?php
$x=1;
$y=$x;
echo $y;
?>
1
<?php
$x=1;
$y= clone $x;
echo $y;
?>
Fatal error: Uncaught Error: __clone method called on non-object in [...][...]:3 Stack trace: #0 {main} thrown in [...][...] on line 3
I never worked with object oriented programming thoroughly so I might need some background knowledge to understand an explanation about this case.
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.