我正在构建一个小型MVC系统,我希望我的控制器成为Singletons。我使基本控制器“控制器”成为一个单独的控制器,并且每个其他控制器都从中扩展。我的路由器处理来自URL的请求并获取控制器字符串名称。
这是我获取私有构造函数错误的地方,因为我正在尝试这样做:
class IndexController extends Controller {
//the "Index" part comes from the url
}
class Controller {
private $instance;
/**
* Initializes a new Singleton Controller
*/
private function __construct() {
}
/**
* Get the instance of the Controller
*/
public static function getInstance(){
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
$className = "Controller";
$inst = new $className; //here is where i get the error
$inst = $className::getInstance() //also fails
我已经完成了我的研究,我偶然发现了这个问题(http://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php),但我不确定这是否有效,或者是最好的方法。
答案 0 :(得分:4)
$inst = new $className; //here is where i get the error
这个错误是正确的,因为构造函数是私有的。
$inst = $className::getInstance() //also fails
此错误也是正确的,因为不允许使用此语法。
如果你想让你的控制者成为单身人士,你可以,但你需要“扭曲”规则。
b.t.w
self
替换为static
,因为这将引用您尝试实例化的实际控制器,而不是Controller
类,因为static
只引用 写的类。扭曲规则:您需要通过工厂实例化您的控制器(这是一种模式)。通常使用前端控制器。
答案 1 :(得分:0)
关于使用“模式”
的错误,有几件事情真的存在class Controller {
private static $instance;
/**
* Initializes a new Singleton Controller
*/
private function __construct() {
}
/**
* Get the instance of the Controller
*/
public static function getInstance(){
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
请注意,该属性现在是静态的,并且构造函数对于此反模式是必要的。
其次,你的调用代码应该是
$instance = Controller::getInstance();
你永远不必从外面实例化'Controller';模式的要点是仅允许通过Controller::getInstance()
据说Singleton比全球国家好一点。 Misko Hevery在Google Clean Code Talk: Global State and Singleton中讨论了它。这是一个非常好的视频,并解释了比我更好的单身人士是坏消息。 sourcemaking.com也有一个很好的write-up on Singletons where they say that Singletons are unnecessary most of the time
答案 2 :(得分:0)
class Controller {
/**
* Let the __construct method be private to prevent new instance though new.
*/
private function __construct() {}
/**
* Get the instance of the Controller
* Here use the lazy loading. (need php >= 5.3)
*/
public static function getInstance(){
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
}
class ControllerA extends Controller {
//You need an static property to hold the instance.
protected static $instance;
}
var_dump($a = ControllerA::getInstance());
var_dump($b = ControllerA::getInstance());
var_dump($a === $b);
如果你的控制器名称是一个字符串,你可以这样做:
$classname = "ControllerA";
call_user_func(array($classname, 'getInstance'));
call_user_func($classname .'::getInstance'); // As of 5.2.3
答案 3 :(得分:-1)
在这一行:
$inst = $className::getInstance() //also fails
您正在使用范围解析运算符。你应该使用这个' - >'用于访问对象数据成员/方法。
$inst = $className->getInstance() //also fails
否则,您需要在类而不是对象上使用范围解析运算符:
$inst = Controller::getInstance() //also fails
我不知道你在哪里获得$ className作为一个类的价值。没有名为IndexController的类。