【问题标题】:PHP magic method __get and [] make value disappearPHP魔术方法__get和[]使值消失
【发布时间】:2026-01-11 19:10:01
【问题描述】:

我遇到了一个有趣的问题。在同一操作中使用 [] 创建一个数组属性并为其赋值似乎会出错。

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);

输出以下内容:

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

所以 1 在数组初始化中真的像戴帽子的兔子一样神奇地消失了。如果我在分配之前尝试所有 $testObj->testArr 甚至将 1 分配为 $testObj->testArr = array(1); - 它工作得很好。但我想了解情况并有一个通用的解决方案,而无需先初始化数组。有没有办法解决这个问题?

【问题讨论】:

  • 您有错误报告吗?
  • 您尝试在创建之前写入$testArr。如果您在第一次写入之前从testArr 阅读,它会起作用:3v4l.org/1ED6K

标签: php arrays properties get


【解决方案1】:
$testObj->testArr[] = 1;

给你一个通知:

注意:间接修改重载属性 T::$testArr 在第 24 行的 test.php 中没有影响

确保您已收到错误报告 turned on

【讨论】:

    【解决方案2】:

    如果您从 __get(或任何函数/方法)返回一个数组,您将返回一个空数组的副本,而不是对该数组的引用。这意味着您正在尝试将元素添加到没有名称且一旦修改就无法访问的变量,因此请注意:

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

    但是,在接下来的两次调用中,键表示的属性是类实例的真实部分,因此不再调用 __get。该变量实际存在,您可以像添加任何其他属于类实例的变量一样附加到它。

    您可以通过向名为 $vals 的类添加一个局部数组变量并更改所有这些代码来看到这是真的

    $this->{$property}
    

    $this->vals[$property]
    

    现在您每次调用 __get 都会收到 3 次通知。

    【讨论】: