__callStatic没有被调用?

时间:2012-11-19 03:57:59

标签: php class static

我知道以下内容可能会在其他地方产生问题并且可能是糟糕的设计,但我仍然想知道为什么会失败(对于我自己的启发):

class Test {
    // singleton
    private function __construct(){}
    private static $i;
    public static function instance(){
        if(!self::$i){
            self::$i = new Test();
        }
        return self::$i;
    }
    // pass static requests to the instance
    public static function __callStatic($method, $parameters){
        return call_user_func_array(array(self::instance(), $method), $parameters);
    }
    private $someVar = 1;
    public function getSomeVar(){
        return $this->someVar;
    }
}

print Test::getSomeVar();

错误为Using $this when not in object context

显然$ this在静态方法中是不可用的,但静态方法是通过call_user_func_array将它交给实例方法调用,这应该使$ this成为实例......

/ EDIT

我知道$ this在静态上下文中不可用。但是,这有效:

print call_user_func_array(array(Test::instance(), 'getSomeVar'), array());

这正是__callStatic重载中发生的事情,所以有些不对......

/编辑2

范围肯定是奇怪的处理。如果你将单例实例拉到任何其他类,它按预期工作:

class Test {
    // singleton
    private function __construct(){}
    private static $i;
    public static function instance(){
        if(!self::$i){
            self::$i = new Blah();
        }
        return self::$i;
    }
    // pass static requests to the instance
    public static function __callStatic($method, $parameters){
        return call_user_func_array(array(static::instance(), $method), $parameters);
    }
}

class Blah {
    private $someVar = 1;
    public function getSomeVar(){
        return $this->someVar;
    }
}

print Test::getSomeVar();

2 个答案:

答案 0 :(得分:9)

您不能通过PHP中的__callStatic调用 staticfy 您的对象方法。只有当目前为止的方法不存在时才会调用它。在您的情况下,Test::getSomeVar()已经定义。

由于向后兼容性,PHP不检查是否只存在静态方法,但实际上通常存在方法。

在您的情况下,您静态调用非静态方法,因此未定义$this,因为尚未调用__callStatic。如果您已将警告和通知启用到最高级别(建议用于开发),PHP会向您发出警告。

因此正确使用:

echo Test::instance()->getSomeVar();

与Singleton的任何其他实现一样。

因此,您只是使用__callStatic错误,它仅适用于尚未定义的 方法。为作业选择其他工具/设计,例如与Blah类一起使用的聚合示例。

进一步说明:

你通常应该阻止在PHP中使用任何静态上下文,特别是当你在这里利用很多魔术功能时,这是另一种气味。在您完成代码之前,之前看起来有很多设计问题。您只会增加难以调试和维护所有这些代码的可能性。但那只是你在一段时间内没有说过你没有被警告过。

如果您想了解更多信息,请参阅Who needs singletons?

答案 1 :(得分:1)

它不起作用。在static调用中,您没有实例,没有对象,也没有$this。调用静态仅适用于$this不可用的静态方法。

文档说:

  在静态上下文中调用无法访问的方法时会触发

__ callStatic()。

我知道这不是你所希望的答案。正如您所预料的那样:您不需要在PHP中进行重载,只需创建您的应用程序并将其保留。