我知道以下可能会在其他地方产生问题并且可能是糟糕的设计,但我仍然想知道为什么会失败(对于我自己的启发):
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();
Run Code Online (Sandbox Code Playgroud)
错误是 Using $this when not in object context
显然$ this是静态方法不可用的,但静态方法是通过call_user_func_array将它交给实例方法调用,这应该使$ this成为实例...
/编辑
我知道$ 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();
Run Code Online (Sandbox Code Playgroud)
hak*_*kre 11
您不能通过PHP中的调用来静态化您的对象方法__callStatic
.只有当目前为止的方法不存在时才会调用它.在你的情况下Test::getSomeVar()
已经定义.
由于向后兼容性,PHP不检查是否只存在静态方法,但实际上通常存在方法.
在您的情况下,您静态调用非静态方法,因此$this
未定义,因为__callStatic
尚未调用.如果您已将警告和通知启用到最高级别(建议用于开发),PHP会向您发出警告.
因此,正确的用法是:
echo Test::instance()->getSomeVar();
Run Code Online (Sandbox Code Playgroud)
与Singleton的任何其他实现一样.
所以,你只是用__callStatic
错了,它仅适用于方法不是没有定义.为作业选择其他工具/设计,例如您在Blah
课堂上使用的聚合示例.
进一步说明:
你通常应该阻止在PHP中使用任何静态上下文,特别是当你在这里利用很多魔术功能时,这是另一种气味.在您完成代码之前,您似乎遇到了一堆设计问题.您只会增加难以调试和维护所有这些代码的可能性.但那只是你没有说在某个时候你没有被警告过.
见谁需要单身?如果你想了解更多.