我知道以下内容可能会在其他地方产生问题并且可能是糟糕的设计,但我仍然想知道为什么会失败(对于我自己的启发):
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();
答案 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中进行重载,只需创建您的应用程序并将其保留。