PHP不同作用域下调用__call与__callStatic出现非预期行为疑问
问题解答
结论
这不是PHP解释器的bug,属于PHP官方定义的正常方法调用解析规则。
原理说明
PHP中的::操作符并不完全等价于「静态调用」,它共有三类合法使用场景:
- 调用类的静态属性/方法
- 调用父类中被当前类覆盖的方法(最常见的场景为
parent::__construct()) - 在类的实例上下文内,调用当前类的方法(即使该方法是非静态的)
当你在A类的非静态方法中执行A::BLA()时,当前上下文存在有效的$this对象,PHP的方法解析器会优先将这个调用判定为「调用当前实例的BLA方法」,而非跨上下文的静态调用。此时BLA方法属于不可访问的实例方法,自然就触发了__call而非__callStatic。
而调用B::BLA()时能正常触发静态魔术方法,是因为B类和当前$this所属的A类没有继承或归属关系,解析器直接将其判定为跨类静态调用,走__callStatic的逻辑。
解决方案
如果需要在对象上下文内强制触发当前类的__callStatic,可以将类名转为字符串形式后再调用,让解析器跳过实例绑定逻辑:
public function doMagicCall_from_objectContext() { $className = self::class; $className::BLA(); // 此时会正确触发__callStatic B::BLA(); }
内容的提问来源于stack exchange,提问作者Patryk
相关产品推荐
相关产品推荐

