通过魔术方法(__get和__set)修改PHP数组元素


Modifying a PHP array element via magic methods (__get and __set)

我有以下类:

/**
 * @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;
    }
}

可以看到,$barMagic公共属性没有显式定义,它是通过magic方法访问的。

当在normal属性中设置和修改数组元素时,它工作得很好:

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

输出"1,2",和预期的一样。

但是当使用magic属性时,它不会:

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

输出"1,1"!

是否有一种方法在PHP访问数组元素在魔术属性的相同方式作为正常的?

ArrayAccess接口处理数组访问的级别似乎比我需要的要高一级。

真正的答案是棘手的,涉及PHP引擎中的一些错误/不一致。正如评论者建议的那样,我加上了"&"(返回引用)字符在__get()之前。新代码:

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

但是这里给出

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

我必须把它改成

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

,现在它工作了。请注意,这两个代码片段应该是完全相等的,但事实并非如此。谢谢大家的帮助,你们让我成功了一半。