Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PHP assignment behave this way?

Tags:

php

I thought PHP = was a simple value assignment. For example:

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

Produces 21 as expected. However, the below code behaves different then what I expected. I was basically trying 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);
}

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 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 the same value to many PHP variables and manipulate them without having them in this "quantum entanglement" state and without copying?

like image 554
q.Then Avatar asked Jan 06 '16 05:01

q.Then


People also ask

How to assign in PHP?

Assignment by reference is also supported, using the "$var = &$othervar;" syntax. Assignment by reference means that both variables end up pointing at the same data, and nothing is copied anywhere. The new operator returns a reference automatically, as such assigning the result of new by reference is an error.

What does& in PHP?

An ampersand just before the function name will return a reference to the variable instead of returning its value. Returning by reference is useful when you want to use a function to find to which variable a reference should be bound.

What does += mean in PHP?

The + operator is the addition operator. += will add numeric values.


2 Answers

You have assigned variable $a and $b with same object. So if you call $a["object"]->doSomething() or $b["object"]->doSomething() will give same result because $a["object"] and $b["object"] are same.

If you need outputs to be different, try below code:

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);
}

Output will be as below :

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 are assigning different object to $a an $b.

Please check this

like image 79
Ijas Ahamed N Avatar answered Oct 06 '22 00:10

Ijas Ahamed N


As of PHP 5, all objects are passed and assigned by reference

Take your code below

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

Reason why you got the unexpected result:

What exactly happens here is , $a and $b are just like 'pointers' or 'handlers' pointing to that same object $template and thats the reason you met something unexpected cos you changed the object through the one of the references $a and since $b also references the same object, you noticed the change

From PHP Manual Objects and References

One of the key-points of PHP5 OOP that is often mentioned is that "objects are passed by references by default". This is not completely true. This section rectifies that general thought using some examples.

A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP5, 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.

like image 33
Abhinav Avatar answered Oct 05 '22 23:10

Abhinav