1

I have the following class:

/**
 * @property int $barMagic
 */
class Foo
{
    public $barNormal;

    private $attributes = [];

    public function __get($name) {
        return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
    }

    public function __set($name, $value)
    {
        $this->attributes[$name] = $value;
    }
}

As you can see, the $barMagic public property is not defined explicitly, it's accessed via the magic methods.

When setting and then modifying an array element in the normal attribute, it works fine:

$foo = new Foo();
$foo->barNormal = ['baz' => 1];
echo $foo->barNormal['baz'];
$foo->barNormal['baz'] = 2;
echo ',' . $foo->barNormal['baz'];

It outputs "1,2", just as intended.

But when using the magic property, it does not:

$foo = new Foo();
$foo->barMagic = ['baz' => 1];
echo $foo->barMagic['baz'];
$foo->barMagic['baz'] = 2;
echo ',' . $foo->barMagic['baz'];

It outputs "1,1"!

Is there a way in PHP to access array elements in magic properties the same way as normal ones?

The ArrayAccess interface seems to deal with array access one level higher than I need it.

Henrique Barcelos
  • 7,670
  • 1
  • 41
  • 66
David Veszelovszki
  • 2,574
  • 1
  • 24
  • 23

1 Answers1

0

The real answer is tricky and involves some bug/inconsistency in the PHP engine. As commentors suggested, I added the "&" (return by reference) character before __get(). So new code:

public function &__get($name) {
    return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
}

but this gives

Notice: Only variable references should be returned by reference in ....

I had to change it to

public function &__get($name) {
    if (isset($this->attributes[$name])) {
        return $this->attributes[$name];
    } else {
        return null;
    }
}

and now it works. Note that the two snippets should be completely equivalent, but they are not. Thank you all for the contribution, you took me halfway there.

David Veszelovszki
  • 2,574
  • 1
  • 24
  • 23
  • This would be interesting in the `else` case, as I don't think you can return a reference to `null`. Need to test this though. – Bert Peters Aug 11 '15 at 15:50