为何PHP类成员方法中调用静态不存在方法时触发__call而非__callStatic?
PHP中__call意外触发而非__callStatic的原因分析
在非静态成员方法内部,使用类名::不存在的静态方法()调用时,PHP会优先将其解析为对象方法调用,而非静态方法调用,这就是为什么__call被触发而不是预期的__callStatic。
核心原因
当代码处于非静态上下文(即成员方法内部,此时存在$this对象)时,PHP的方法解析规则会优先绑定到当前对象。即使你写了Test::nonExistingStaticMethod(),PHP仍会尝试在当前对象上查找该方法——找不到时就触发对象的__call魔术方法,而非静态类的__callStatic。
验证与解决
验证:切换到静态上下文
将wtf方法改为静态方法,此时上下文无$this,调用会触发__callStatic:
class Test { public function __call($name, $params){ echo "__call()"; } public static function __callStatic($name, $params){ echo "__callStatic()"; } public static function wtf(){ Test::nonExistingStaticMethod(); } } $test = new Test(); $test->wtf(); // 输出:__callStatic()
解决:强制静态调用(非静态上下文内)
如果需要在非静态方法里触发__callStatic,可以使用forward_static_call强制走静态方法解析流程:
public function wtf(){ forward_static_call(['Test', 'nonExistingStaticMethod']); // 输出:__callStatic() }
原问题代码
<?php class Test { public function __call($name, $params){ echo "__call()"; } public static function __callStatic($name, $params){ echo "__callStatic()"; } public function wtf(){ Test::nonExistingStaticMethod(); } } $test = new Test(); $test->wtf(); // expected: __callStatic , actually: __call
内容的提问来源于stack exchange,提问作者br4nnigan
相关产品推荐
相关产品推荐

