You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何给不存在的对象属性赋值引用时会调用__get()魔术方法?

PHP引用赋值与普通赋值的重载属性行为差异

代码示例1(引用赋值)

class Test
{
    public $prop1;
    public function __get(string $n)
    {
        echo '__GET: '.$n.' - but why?<br>';
        die;
    }
}

$t = new Test();
$x1 = new \stdClass();
$t->prop2 = &$x1;
echo '.';
die;

现象:尝试将stdClass对象的引用赋值给不存在的prop2属性时,__get()方法被执行;若移除die(),会抛出Indirect modification of overloaded property has no effect异常。

代码示例2(普通赋值)

class Test
{
    public $prop1;
    public function __get(string $n)
    {
        echo '__GET: '.$n.' - but why?<br>';
        die;
    }
}

$t = new Test();
$x1 = new \stdClass();
$t->prop2 = $x1;
echo '.';
die;

现象:程序运行正常,不会触发__get()方法。

为什么会出现这种差异?

这得从PHP的属性重载逻辑和引用赋值的底层机制说起:

  • 普通赋值的逻辑:当执行$t->prop2 = $x1时,这是直接对不存在的属性执行赋值操作。PHP默认会自动为$t对象添加prop2这个公共属性,整个过程不会触发__get()(__get()仅在读取不存在/不可访问的属性时才会被调用),所以程序正常运行。
  • 引用赋值的逻辑:引用赋值$t->prop2 = &$x1的本质是要把$x1的引用绑定到$t->prop2这个属性上。这时候PHP需要先找到$t->prop2对应的「变量容器」,但这个属性不存在,于是PHP会调用__get()尝试获取该属性。但__get()返回的是临时值(而非可绑定引用的容器),后续尝试给这个临时值绑定引用时就会失败,进而触发异常——这也是__get()被触发的核心原因。

如果要让引用赋值正常工作,需要在类中定义__set()方法处理不存在的属性赋值,结合类内部数组存储属性来支持引用绑定。


内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 05:20:49