为何添加__isset()魔术方法后,仅第二次调用isset()时才触发它?
PHP中__isset()魔术方法触发时机解析
场景1:未定义__isset()魔术方法的情况
class X { protected string $foo; public function test_isset() { var_dump(isset($this->foo)); unset($this->foo); var_dump(isset($this->foo)); } } (new X())->test_isset();
执行结果:
false false
该结果符合逻辑:$foo属性未被赋值,第一次isset()返回false;unset()后属性不存在,第二次isset()也返回false。
场景2:新增__isset()魔术方法的情况
与场景1一致,但新增__isset()魔术方法,调用时输出提示信息:
class X { protected string $foo; public function __isset($name) { echo "__isset\n"; return isset($this->foo); } public function test_isset() { var_dump(isset($this->foo)); // false unset($this->foo); var_dump(isset($this->foo)); // false } } (new X())->test_isset();
执行结果:
false __isset false
问题解析:为何仅第二次调用isset()时触发__isset()?
核心原因在于PHP对isset()调用的处理逻辑:
- 第一次调用:类内部定义了
protected $foo属性,当前对象实例中该属性是存在的,只是未被赋值(值为null)。此时PHP会直接检查属性的存在性和值状态,因为属性存在且有权限访问,所以直接返回isset(null)的结果false,不会触发__isset()魔术方法。 - 第二次调用:执行
unset($this->foo)后,该属性被从当前对象实例的属性集合中彻底移除。此时PHP检查$this->foo时,发现实例中已不存在该属性,于是触发__isset()魔术方法来处理这个属性检查请求,所以会输出__isset提示,之后方法内部返回isset($this->foo)的结果false。
内容的提问来源于stack exchange,提问作者LordF
相关产品推荐
相关产品推荐

