John Davidson

PHP class: referenced variable in one method affects non-referenced variable in other method

0 comments
Message:


I'm puzzled by the behaviour in the following example. I stumbled over this in a project and it took me hours to narrow the problem down to a simple example. So this is my simple test class:


<?php
class Foo {
public $sess = [['name' => 'John']];

public function info() {
$this->runTest();
echo $this->sess[0]['name'];
}

private function runTest() {
$localSess = &$this->sess[0];
$this->sessTest();
}

private function sessTest() {
$sessCopy = $this->sess;
$this->sess[0]['name'] = 'Bob';
$this->sess = $sessCopy;
}
}

$myFoo = new Foo;
$myFoo->info();

The unexpected resulting output is:



Bob



If $localSess is just a simple assignment and not a reference, the output is (as expected): John


I don't understand what's going on here. Since the class property $sess is an array and not an object, the assignment to $sessCopy should be a simple copy. But if you print the content of $sessCopy right after modifying $this->sess, it will contain the changed value for 'name'. So it seems as if $sessCopy were a reference after all? But only if $localSess in the calling method is a reference. Why should that even matter? BTW, if $localSess is a reference to the whole array of the class property and not just to its first index, everything works as expected.


Can someone please shed some light on this? If the mere existence of a variable reference in one function can influence the content of a local variable (not a reference!) in another function, then that seems dangerous and scary.



My Answer:
php
class Test {
private $data = [];

public function addValue(&$value) {
$this->data[] = $value;
}

public function printData() {
print_r($this->data);
}
}

$obj = new Test();
$value = 1;
$obj->addValue($value);
$obj->printData(); // Output: Array ( [0] => 1 )
$value = 2;
$obj->printData(); // Output: Array ( [0] => 2 )


In this example, we have a `Test` class with a private property `$data` which is an array. We have two methods: `addValue` which takes a reference to a variable and adds it to the `$data` array, and `printData` which simply prints out the contents of the `$data` array.

When we create an instance of the `Test` class and call `addValue` with a variable `$value`, it adds the value of `$value` to the `$data` array. However, when we change the value of `$value` and call `printData` again, the value in the `$data` array also changes. This is because we passed `$value` by reference to the `addValue` method, so any changes to `$value` outside of the method will affect the value in the `$data` array.

To avoid this behavior, you can remove the reference in the `addValue` method signature like this:

php
public function addValue($value) {
$this->data[] = $value;
}


Now, changing the value of `$value` outside of the method will not affect the value in the `$data` array.

Rate this post

3 of 5 based on 1500 votes

Comments




© 2024 Hayatsk.info - Personal Blogs Platform. All Rights Reserved.
Create blog  |  Privacy Policy  |  Terms & Conditions  |  Contact Us