Why does PHP behave like this?

I thought PHP = is a simple assignment of values. For instance:

 $x = 1; $a = $x; $b = $x; $a++; echo $a; echo $b; 

Produces 21 , as expected. However, the code below behaves differently than I expected. I basically tried to assign the "same" value to many variables:

 class X { public $val = 0; public function doSomething() { $this->val = "hi"; } } function someFunction() { $template = array('non_object' => 0, 'object' => new X()); $a = $template; $b = $template; //Do something $a['object']->doSomething(); var_dump($a); var_dump($b); } 

It produces:

 array(2) { ["non_object"]=> int(0) ["object"]=> object(X)#1 (1) { ["val"]=> string(2) "hi" } } array(2) { ["non_object"]=> int(0) ["object"]=> object(X)#1 (1) { ["val"]=> string(2) "hi" } } 

As you can see, the object property in array A has changed as expected, but also changed in array B

You can check the code here: http://sandbox.onlinephpfunctions.com/code/bff611fc9854b777114d38a3b4c60d524fdf2e19

How can I assign one value to many PHP variables and manipulate them without having them in this state of "quantum entanglement" and without copying?

+6
source share
3 answers

Starting with PHP 5, all objects are passed and assigned by reference

Take the code below

  $a = $template; $b = $template; 

The reason you got an unexpected result:

What exactly is happening, $a and $b are like “pointers” or “handlers” pointing to the same $template object, and this is the reason you came across something unexpected because you changed the object to one link $a , and since $b also refers to the same object, you notice a change

From the PHP Manual Objects and Links

One of the key points of OOP PHP5, which is often mentioned, is that "Objects are passed by default." This is not entirely true. In this section, you can correct this general idea using some examples.

A PHP reference is an alias that allows two different variables to write to the same value. Starting with PHP5, an object variable no longer contains an object as a value. It contains only the object identifier, which allows object accessories to find the actual object. When an object is sent by argument, a variable is returned or assigned to another, different variables are not aliases: they contain a copy of an identifier that points to the same object.

+1
source

You assigned the variables $ a and $ b with the same object. Therefore, if you call $a["object"]->doSomething() or $b["object"]->doSomething() , you will get the same result because $a["object"] and $b["object"] will be the same.

If you need different outputs, try the code below:

 class X { public $val = 0; public function doSomething() { $this->val = "hi"; } } function someFunction() { $a = array('non_object' => 0, 'object' => new X()); $b = array('non_object' => 0, 'object' => new X()); //Do something $a['object']->doSomething(); var_dump($a); var_dump($b); } 

The output will be as follows:

 array(2) { ["non_object"]=> int(0) ["object"]=> object(X)#1 (1) { ["val"]=> string(2) "hi" } } array(2) { ["non_object"]=> int(0) ["object"]=> object(X)#2 (1) { ["val"]=> int(0) } } 

Here you assign another object $ aa $ b.

Please check it

+5
source

If you want to assign only a value, you can use the function: clone

 class X { public $val = 0; public function increment() { $this->val += 1; } } function someFunction() { $template =new X(); $a = $template; $b = clone $template; //Increment a $a->increment(); var_dump($a); var_dump($b); } someFunction(); $x = 1; $a = $x; $b = $x; $a++; echo $a; echo $b; 

check this

+1
source

All Articles