Создание экземпляра PHP Singleton с именем класса String - PullRequest
0 голосов
/ 29 января 2012

Я строю небольшую систему MVC, и я хочу, чтобы мои контроллеры были синглетонами. Я сделал базовый контроллер «Контроллер» синглтоном, и все остальные контроллеры расширяются от этого. Мой маршрутизатор обрабатывает запрос с 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 ]

4 голосов
/ 29 января 2012

$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 ссылается на только класс, в котором он написан.

Перепутывание правил: вам нужно будет создавать экземпляры ваших контроллеров через фабрику (это шаблон). Обычно для этого используется фронтальный контроллер.

0 голосов
/ 29 января 2012
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
0 голосов
/ 29 января 2012

В этой строке:

$inst = $className::getInstance() //also fails

Вы используете оператор разрешения области.Вы должны использовать это '->' для доступа к элементам / методам данных объекта.

$inst = $className->getInstance() //also fails

В противном случае вам нужно использовать оператор разрешения области действия для класса, а не для объекта:

$inst = Controller::getInstance() //also fails

Я не знаю, откуда вы получаете значение из $ className как класса.Нет класса с именем IndexController.

0 голосов
/ 29 января 2012

Несколько вещей, касающихся ошибок при использовании «шаблона»-pattern.

Во-вторых, ваш вызывающий код должен выглядеть так:

$instance = Controller::getInstance();

Вам никогда не придется создавать экземпляр Controller извне;смысл паттерна в том, чтобы разрешить доступ только через Controller::getInstance()


При этом Синглтон немного лучше глобального состояния.Миско Хевери рассказывает об этом в этом Google Clean Code Talk: Global State и Singleton .Это действительно хорошее видео, и оно гораздо лучше, чем я, объясняет, почему «Синглтоны» - плохие новости. sourcemaking.com также имеет хорошую рецензию на синглтоны, где говорится, что синглтоны в большинстве случаев не нужны

...