get_instance () в Codeigniter: зачем назначать его переменной?

В Codeigniter get_instance() – глобально доступная функция, которая возвращает супер-объект Controller, который содержит все загруженные классы (он возвращает экземпляр класса Controller). Я буду включать текущий исходный код:

get_instance() определяется в Codeigniter.php

 // Load the base controller class require BASEPATH.'core/Controller.php'; function &get_instance() { return CI_Controller::get_instance(); } 

И CI_Controller определяется в Controller.php

 class CI_Controller { private static $instance; /** * Constructor */ public function __construct() { self::$instance =& $this; // Assign all the class objects that were instantiated by the // bootstrap file (CodeIgniter.php) to local class variables // so that CI can run as one big super object. foreach (is_loaded() as $var => $class) { $this->$var =& load_class($class); } $this->load =& load_class('Loader', 'core'); $this->load->set_base_classes()->ci_autoloader(); log_message('debug', "Controller Class Initialized"); } public static function &get_instance() { return self::$instance; } } 

Вот как это рекомендуется использовать в руководстве пользователя для создания библиотек :

Использование ресурсов CodeIgniter в вашей библиотеке

Для доступа к собственным ресурсам CodeIgniter в вашей библиотеке используйте get_instance() . Эта функция возвращает суперъект CodeIgniter.

Обычно из ваших функций контроллера вы вызываете любую из доступных функций CodeIgniter, используя $this construct: $this->load->helper('url'); $this->load->library('session'); $this->config->item('base_url'); $this->load->helper('url'); $this->load->library('session'); $this->config->item('base_url'); и т.п.

$this , однако, работает только внутри ваших контроллеров, ваших моделей или ваших просмотров. Если вы хотите использовать классы CodeIgniter из своих собственных пользовательских классов, вы можете сделать это следующим образом:

Сначала назначьте объект CodeIgniter переменной:

$ CI = & get_instance ();

Когда вы назначили объект переменной, вы будете использовать эту переменную вместо $this : $ CI = & get_instance (); $ CI-> load-> помощник ( 'URL'); $ CI-> load-> библиотека ( 'сессии'); $ CI-> config-> пункт ( 'base_url'); и т.п.

Примечание. Вы заметите, что вышеуказанная get_instance() передается по ссылке:

$ CI = & get_instance ();

Это очень важно. Присвоение по ссылке позволяет использовать исходный объект CodeIgniter, а не создавать его копию.

Похожие сообщения: объяснять $ CI = & get_instance (); / Codeigniter: Получить экземпляр

Итак, вот мой вопрос:

Почему руководство пользователя рекомендует присваивать get_instance() переменную? Я совершенно уверен, что понимаю последствия не назначения ссылки, но почему рекомендуется назначать ее переменной, когда get_instance()->load->model() работает нормально?

Я вижу много определенных пользователем или сторонних классов в CI, которые присваивают свойству объекта:

 class MY_Class { private $CI; function __construct() { $this->CI =& get_instance(); } function my_func() { $this->CI->load->view('some_view'); } function my_other_func() { $this->CI->load->model('some_model'); } } 

Плохой пример, но я часто это вижу. Зачем беспокоиться об этом методе, а не просто вызвать get_instance() напрямую? Кажется, что присвоение всего объекта Controller переменной класса не будет отличной идеей, даже если это ссылка. Может быть, это неважно.

Я хочу написать функцию-обертку для get_instance() поэтому ее легче набирать, и мне не нужно постоянно назначать ее переменной.

 function CI() { return get_instance(); } 

Или:

 function CI() { $CI =& get_instance(); return $CI; } 

Тогда я мог бы использовать CI()->class->method() из любой точки мира, без необходимости назначать его переменной, ее очень легко написать и понять, что она делает, и может привести к более коротким и более элегантным кодам.

  • Есть ли причина не принимать такой подход?
  • Есть ли разница между двумя функциями CI() выше?
  • Почему рекомендуется назначать get_instance() для переменной, а не вызвать ее напрямую?
  • Что означает function &get_instance(){} & in function &get_instance(){} где она определена? Я немного разбираюсь в том, что такое ссылки , и я использую их, когда это необходимо, но я никогда не видел функцию, определенную таким образом. Если я пишу функцию обертки, должен ли я использовать ее также?

Обратите внимание, что это не столько вопрос стиля , сколько технический. Я хочу знать, есть ли какие-либо проблемы, производительность или нет , используя метод, который я предлагаю.

EDIT : До сих пор мы имеем:

  • Цепочка метода недоступна в php4, поэтому присвоение переменной является обходным решением (хотя это довольно неуместно, поскольку Codeigniter отказался от поддержки php4)
  • Небольшие накладные расходы на вызов функции более одного раза для возврата объекта, а не вызов его один раз и назначение переменной.

Что-нибудь еще, или это единственные потенциальные проблемы?

Насколько я знаю, это вопрос удобства больше всего. Скорее всего, вы будете использовать супер-объект CI в своих библиотеках, поэтому почему бы не назначить его переменной, чтобы сделать ее немного легче работать?

Есть еще несколько вещей, которые нужно учитывать …

  1. Если вы помещаете этот метод в помощник, этот метод становится зависимым для любого класса, в котором вы его используете. Это может быть не очень важно для вас, но если вы хотите делиться библиотеками с кем-то еще, они могут быть недовольны потому что уже существует стандартный способ обработки этого в сообществе CI.
  2. Есть небольшое влияние на производительность, потому что вы вызываете get_instance() каждый раз, когда используете помощника, а не сохраняете его результат в переменной.
  3. Поскольку это вспомогательный метод, который должен сэкономить ваше время, для тех, кто работает главным образом в основных файлах MVC CI, настройка такого помощника займет больше времени, чем просто установка переменной в несколько мест, в которых вы нуждаетесь Это.

Почему рекомендуется назначать get_instance () для переменной, а не вызвать ее напрямую?

Скорее всего, рекомендуется поддерживать обратную совместимость с php4, где объекты по умолчанию не передавались по ссылке, а были клонированы.

Есть ли причина не принимать такой подход?

Только если вы хотите, чтобы ваше приложение выполнялось на устаревших установках php

Необходимо назначить по ссылке, потому что значение CI_Controller::$instance может быть изменено, если создается другой экземпляр класса. Конструктор повторно назначает self::$instance каждый раз, когда он запускается.

В общем, это похоже на плохой шаблон дизайна и отсутствует свойство singleton, которое ограничивает класс только одним экземпляром, http://en.wikipedia.org/wiki/Singleton_pattern .

Кажется возможным набрать, CI_Controller::get_instance()->$className->$method(); который, похоже, больше набирает ваш запрошенный CI()->$className->$method .

В конечном итоге было бы разумно потребовать, чтобы был создан только один экземпляр экземпляра $instance а затем необходимость в назначении по ссылке была бы устранена.

Цепочка метода не поддерживается в PHP4 а CI потеряла поддержку PHP4 совсем недавно (с версии 2.0.0 ). Также легко писать $CI чем писать get_instance() каждый раз.

Это может быть комбинация нескольких вещей, в том числе уже упомянутых:

  • Обратная совместимость
  • удобство
  • Гид по стилю

Предпочтительно, мне нравится идея этой «рекомендации» как часть руководства по стилю. Возможно, это не официальный стиль руководства CI, но все же.

Представьте, что все сторонние скрипты для CI реализуют эту рекомендацию, любой разработчик сможет быстро определить, как эти сценарии разработаны, хотя это просто очень маленькая часть скрипта.

Еще одна важная особенность IMO – это механика цепочки методов, а метод CI()->class->method() не казался бы интуитивным для меня, зная, как работает остальная часть CI.

Я предпочитаю использовать этот способ, это просто

 class Test { //magic method __get, whit this can use $this->load //instead create a variable ci, then do $this->ci->load, cool :) public function __get($var) { return get_instance()->$var; } public function showUrl() { $this->load->helper("url"); echo base_url(); } } 

Получение результата get_instance() по ссылке просто не имеет смысла с PHP5. К сожалению, эта дурная привычка, похоже, глубоко укоренилась, поэтому давайте просто справимся с этим.

Для тех, кто интересуется, вот пример быстрого получения экземпляра über:

 function CI() { static $CI; isset($CI) || $CI = CI_Controller::get_instance(); return $CI; } 

Обратите внимание, что статическая переменная не работает, если она была назначена ссылкой.

Кроме того, вы вынуждены не ссылаться на результат этого CI() . Дополнительный сахар 🙂

Ах, и, очевидно, у вас все еще есть (небольшая) стоимость вызова функции. Вы все еще можете использовать переменную вместо вызова функции десятки раз.