为何调用PHP静态方法仅用单冒号不触发Parse Error?
为什么PHP中单冒号调用类静态方法不报错,反而执行了全局函数?
先看这段有“问题”的代码:
<?php class ABC { static function xyz() { echo "I don't like the alphabet"; } } ABC:xyz(); // 定义在别处的全局函数 function xyz() { echo "xyz\n"; }
看起来应该是想用ABC::xyz()调用类的静态方法,但写成了单冒号,奇怪的是它没有触发语法错误,反而输出了xyz——也就是执行了全局的xyz()函数。
背后的原因
PHP把ABC:xyz()解析成了两个独立的部分:
ABC::这是PHP的**标签(Label)**语法,用于goto语句的跳转标记,语法规则就是标识符:,这里ABC被当作一个标签名,哪怕你没用到goto跳转,标签本身也是合法语法。xyz():直接调用全局作用域下的xyz()函数。
至于为什么ABC作为标签名不会报错?因为PHP在遇到未定义的标识符作为标签时,不会抛出错误;同时,这里的ABC没有被当作类名解析,是因为单冒号不是类成员访问的语法(类成员访问必须用双冒号::)。
另外你提到PHP 5.2会报错,是因为在PHP 5.2及更早版本中,当解析到ABC:时,会把ABC当作未定义常量处理并直接抛出错误;而PHP 5.3及之后的版本,对未定义常量的处理改为了发出警告(默认环境下可能不显示警告),同时将未定义常量名当作字符串处理,所以标签语法能正常通过解析,后续的函数调用也能执行。
如何避免这类问题
- 开启严格错误提示:开发环境中设置
error_reporting(E_ALL),这样未定义常量的警告会被显示,能及时发现这类语法歧义; - 严格遵守语法规范:调用类静态方法时必须用双冒号
::,不要手滑写成单冒号; - 使用静态代码分析工具:比如PHPStan、Psalm,这类工具能在代码运行前就检测出这种不符合语法预期的写法。
内容的提问来源于stack exchange,提问作者SeanDowney
相关产品推荐
相关产品推荐

