3

I've faced one interesting problem. Creating an array property and assigning a value into it in the same operation using [] seems to go 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 is really magically disappeared in the array initialization like a rabbit in the hat. If i try to all $testObj->testArr before the assignment or even assign 1 as $testObj->testArr = array(1); - it works just fine. But i would like to understand the situation and have a universal solution without a need to init the array first. Is there a way to deal with this?

mmking
  • 1,564
  • 4
  • 26
  • 36
dayan
  • 403
  • 1
  • 4
  • 12

2 Answers2

4
$testObj->testArr[] = 1;

Gives you a notice:

Notice: Indirect modification of overloaded property T::$testArr has no effect in test.php on line 24

Make sure you've got your error reporting turned on.

Community
  • 1
  • 1
Halcyon
  • 57,230
  • 10
  • 89
  • 128
0

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 you are trying to add an element to a variable which has no name and can not be accessed once you modify it, thus 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 a real part of the class instance, so __get isn't being called anymore. The variable actually exists and you are appending to it as you would any other variable that is part of a class instance.

You can see this is true by adding a local array variable to the class called $vals, and changing all this code

$this->{$property}

To

$this->vals[$property]

Now you get the notification 3 times, for each call of __get.

Chris Nasr
  • 145
  • 1
  • 9