最近在 PHP 8 环境下,发现 #WPJAM Basic# 的一个严重问题:就是后台文章和分类列表的一些操作无效了,点击保存按钮没有任何反应。经过深入调试,发现问题根源在于 PHP 8 对is_callable()
函数的行为进行了重大调整。
在 PHP 8 之前,is_callable()
函数在检查类名与非静态方法的组合时会返回 true
,即使这种调用方式在实际执行时可能会导致问题。PHP 8 对此进行了更严格的检查,以提前发现潜在的错误调用方式,因此 is_callable()
在检查一个类名与非静态方法时将返回失败(应当检查一个类的实例)。
具体看下面这个例子就大概能够明白了:
class Test{
public function method1() { }
public static function method2() { }
}
// PHP 8 之前
var_dump(is_callable(['Test', 'method1'])); // bool(true)
var_dump(is_callable(['Test', 'method2'])); // bool(true)
// PHP 8 之后
var_dump(is_callable(['Test', 'method1'])); // bool(false)
var_dump(is_callable(['Test', 'method2'])); // bool(true)
var_dump(is_callable([new Test, 'method1'])); // bool(true)
PHP 8 的这一变更是为了更严格地执行面向对象编程规范:
is_callable()
会返回 true
,但实际以静态方式调用非静态方法时会产生警告。PHP 8 通过 is_callable()
提前返回 false
来更早发现问题。既然知道这个原因,那就是代码要根据上下文来写了。所以如果要检查某个对象的非静态方法是否可调用,应该使用一个对象实例而不是类名。
此外,其实很多时候我们只需要检查类的方法是否存在,而不关心其可调用性(例如访问控制),那么可以简单使用 method_exists()
进行判断就好了:
if (method_exists('Test', 'method1')) {
// Do something
}