PHP magic method __get and [] make the value disappear

I ran into one interesting problem. Creating an array property and assigning a value to it in the same operation using [] seems to be wrong.

class T
{
    public function __get($property)
    {
        if (!isset($this->{$property}))
        {
            $this->{$property} = array();
        }           

        return $this->{$property};
    }

    public function __set($key, $val)
    {       
        $this->{$key} = $val;
    }

}

$testObj = new T();

$testObj->testArr[] = 1;
$testObj->testArr[] = 2;    
$testObj->testArr[] = 3;

var_dump($testObj->testArr);

      

Outputs the following:

array(2) { [0]=> int(2) [1]=> int(3) }

      

So 1 really magically disappeared into array initialization like a rabbit in a hat. If I try to execute all $ testObj-> testArr before assignment, or even assign 1 as $ testObj-> testArr = array (1); - it works great. But I would like to understand the situation and have a universal solution without having to initialize the array first. Is there a way to handle this?

+3


source to share


2 answers


$testObj->testArr[] = 1;

      

Gives you a notification:



Note: indirect modification of the overloaded property T :: $ testArr does not affect test.php on line 24

Make sure you have an error message.

+3


source


If you return an array from __get (or any function / method), you are returning a copy of the empty array, not a reference to that array. This means that you are trying to add an item to a variable that has no name and cannot be accessed after changing it, so the notice:

PHP Notice:  Indirect modification of overloaded property T::$testArr has no effect

      

However, on the next two calls, the property represented by the key is the real part of the class instance, so __get is no longer called. The variable actually exists and is added to it like any other variable that is part of an instance of the class.

You can see that this is correct by adding a local array variable to a class named $ vals and changing all of this code



$this->{$property}

      

For

$this->vals[$property]

      

Now you get notified 3 times, for each call to __get.

0


source







All Articles