Reputation: 2753
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?
Upvotes: 6
Views: 173
Reputation: 8168
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.
Upvotes: 1
Reputation: 639
If you want to assign value only, u can use 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;
Upvotes: 1
Reputation: 6110
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.
Upvotes: 4