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

未声明属性"example"可调用?代码运行及echo输出次数疑问

问题解答

咱们逐个拆解你的疑问:

1. 能否在未声明的情况下调用名为"example"的属性?

完全可以!在PHP中,当你尝试给类中未定义的属性(或是当前上下文无权限直接访问的私有/受保护属性)赋值时,PHP会自动触发__set()魔术方法来处理这个操作——这也是你的代码能正常运行的核心原因。

2. 这段代码为什么能正常运行?

你的代码核心就是利用了PHP的__set()魔术机制:

  • 当执行$obj->example = "<strong>hello</strong>";时,因为SetMissing类里并没有预先定义$example属性,PHP会自动调用__set()方法。
  • 在__set()方法里,你做了两件关键事:打印_SET,然后通过$this->$name = ...把过滤后的值赋值给了这个动态创建的属性。注意:这一步执行完后,$obj对象里就实实在在存在$example属性了!
  • 后续再访问$obj->example时,因为属性已经存在,就直接返回对应的值,不会再触发魔术方法。

完整的代码执行流程可以拆解为:

class SetMissing { 
    public function __set($name, $value) { 
        echo "_SET"; 
        // 动态创建属性并赋值
        $this->$name = filter_var($value, FILTER_SANITIZE_STRING); 
    } 
} 

$obj = new SetMissing(); 
// 第一次赋值:example不存在,触发__set(),打印_SET,同时创建example属性并赋值为过滤后的"hello"
$obj->example = "<strong>hello</strong>"; 
// 直接读取已存在的example属性,输出"hello"加换行
echo $obj->example . PHP_EOL ; 
// 第二次赋值:example已存在,直接覆盖值,不会触发__set()
$obj->example = "<strong>hello</strong>"; 
// 读取已存在的属性,输出"hello"
echo $obj->example;

3. 为什么_SET仅打印一次而不是两次?

原因很直白:

  • 第一次给example赋值时,属性不存在,触发__set(),所以打印了_SET,同时动态创建了example属性。
  • 第二次赋值时,example已经是$obj对象的一个实际属性了,PHP会直接对这个已有属性做赋值操作,不会再触发__set()魔术方法,自然也就不会再打印_SET。

如果想要每次赋值都触发__set(),可以把属性的存储逻辑改成私有数组(避免直接创建公共属性),比如:

class SetMissing { 
    private $properties = [];
    
    public function __set($name, $value) { 
        echo "_SET"; 
        $this->properties[$name] = filter_var($value, FILTER_SANITIZE_STRING); 
    } 

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

这样每次外部赋值都会触发__set(),_SET就会打印两次了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:12:13