通过作用域解析运算符调用非静态方法


Invoking a non-static method via the scope resolution operator

我发现PHP解释器有一些奇怪的行为,我不确定在生产中使用它是否安全。

当我们调用Foo::bar(),而Foo类没有静态bar方法,但它有非静态bar方法时,解释器会在null上调用非静态的bar(是的,这听起来很荒谬)。我期望在这种情况下调用__callStatic。但出于某种原因,这并不是正在发生的事情。

然后,我发现了这种行为的一个方便用法:为类提供具有相同名称的静态和非静态方法,如下所示:

class Foo
{
    public function bar(){
        if (isset($this)) {
            $this->nonStaticBar();
        } else {
            static::staticBar();
        }
    }
    private function nonStaticBar() {
        echo "Non-static'n";
    }
    private static function staticBar() {
        echo "Static'n";
    }
}
(new Foo())->bar(); // Output: "Non-static"
Foo::bar(); // Output: "Static"

是的,我知道,这种方法并不优雅,在架构上也是错误的。问题是使用这个"功能"是否安全(符合标准)。当isset($this)可以等于false时,还有其他情况吗?

虽然上面的例子确实有效,但它不是最佳实践。这在这里的PHP文档中得到了认可,并指出在版本7之前的PHP版本中,如果启用了E_STRICT错误报告,则它将发出错误:

Strict Standards: Non-static method Foo::bar() should not be called statically in /Path/to/file.php on line 22

此外,在PHP版本7及更高版本中,静态调用静态函数是不推荐的,并且在执行时会导致以下错误:

Deprecated:  Non-static method Foo::bar() should not be called statically in /Path/to/file.php on line 22