Copying the value of variable Y to variable X in PHP

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.