使用String类名的PHP Singleton实例化

时间:2012-01-29 04:51:22

标签: php singleton instantiation

我正在构建一个小型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),但我不确定这是否有效,或者是最好的方法。

4 个答案:

答案 0 :(得分:4)

$inst = new $className; //here is where i get the error 这个错误是正确的,因为构造函数是私有的。

$inst = $className::getInstance() //also fails 此错误也是正确的,因为不允许使用此语法。

如果你想让你的控制者成为单身人士,你可以,但你需要“扭曲”规则。

b.t.w

  1. 为什么你想要这样做?
  2. 为什么不使用现有的MVC(您不需要整个FW)。
  3. self替换为static,因为这将引用您尝试实例化的实际控制器,而不是Controller类,因为static只引用 写的类。
  4. 扭曲规则:您需要通过工厂实例化您的控制器(这是一种模式)。通常使用前端控制器。

答案 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的类。