Codeigniter中的get_instance():为什么把它分配给一个variables?

get_instance()get_instance()是一个全局可用的函数,它返回包含所有当前加载的类(它返回Controller类实例)的Controller超级对象。 我将包括当前的源代码:

get_instance()get_instance()中定义

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

CI_ControllerController.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; } } 

以下是build议在用户指南中用于创build库的方法 :

在库中使用CodeIgniter资源

要访问库中的CodeIgniter本地资源,请使用get_instance()函数。 这个函数返回CodeIgniter超级对象。

通常从你的控制器函数中,你将使用$this构造函数调用任何可用的CodeIgniter函数: $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对象分配给一个variables:

$ CI =&get_instance();

一旦你将对象赋值给一个variables,你将使用该variables而不是$this :$ CI =&get_instance(); $ CI->负载>帮手( 'URL'); $ CI->负载>库( '会议'); $ CI-> config->项( 'BASE_URL'); 等等

注意:你会注意到上面的get_instance()函数是通过引用传递的:

$ CI =&get_instance();

这个非常重要。 通过引用分配允许您使用原始的CodeIgniter对象,而不是创build它的副本。

相关post: 解释$ CI =&get_instance(); / Codeigniter:获取实例

所以,这是我的实际问题:

为什么用户指南build议将get_instance()分配给variables? 我相当肯定,我明白没有引用分配的含义,但为什么build议将它分配给一个variablesget_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对象分配给一个类variables并不是一个好主意,即使它是一个引用。 也许没关系。

我想为get_instance()编写一个包装器函数,所以input起来比较容易,而且我不必一直把它分配给一个variables。

 function CI() { return get_instance(); } 

要么:

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

然后,我可以从任何地方使用CI()->class->method() ,而不必将它分配给一个variables,这很容易编写和理解它做什么,并可以导致更短,更优雅的代码。

  • 有没有理由不采取这种做法?
  • 上述两个CI()函数是否有区别?
  • 为什么build议将get_instance()分配给variables而不是直接调用?
  • & in function &get_instance(){}是什么意思? 我知道一些关于什么是引用是适用的,但我从来没有见过这样定义的函数。 如果我写封装函数,我也应该使用它?

请注意,这不是一个风格问题,而是一个技术问题。 我想知道是否有任何问题,performance或其他 ,使用我build议的方法。

编辑 :到目前为止我们有:

  • 方法链接在php4中不可用,因此分配给variables是一种解决方法(尽pipe这与Codeigniter已经减less了对php4的支持是毫不相关的)
  • 多次调用一个函数来返回对象的次要开销,而不是调用一次并分配给一个variables。

还有什么,或者这是唯一的潜在问题?

据我所知,这是一个比任何事情都方便的问题。 有可能你会在你的库中使用CI超级对象,为什么不把它分配给一个variables,使它更容易处理?

还有其他一些事情要考虑…

  1. 如果你把这个方法放在帮助器中,那么这个方法就会成为你使用它的任何类的依赖。这对你来说可能不是什么大问题,但是如果你想和其他人共享库,他们可能不会很高兴依赖,特别是因为在CI社区中已经有了一个标准的处理方法。
  2. 对性能有轻微的影响,因为每次使用助手时都要调用get_instance() ,而不是将结果存储在variables中。
  3. 由于这是一个帮助你节省时间的方法,对于那些主要在CI的核心MVC文件中工作的人来说,像这样设置一个助手需要花费的时间比在你需要的less数几个地方设置一个variables要花费更多的时间它。

为什么build议将get_instance()分配给variables而不是直接调用?

最有可能的是,build议保持与php4的向后兼容性,对象不是通过引用默认传递的,而是被克隆的。

有没有理由不采取这种做法?

只有当你想你的应用程序运行在过时的PHP安装

有必要通过引用进行分配,因为如果创build了另一个类的实例,则CI_Controller::$instance值可能会更改。 构造函数每次运行时都会重新分配self::$instance

一般来说,这感觉就像一个糟糕的devise模式,并且缺less一个单例的属性,它将类限制为只有一个实例http://en.wikipedia.org/wiki/Singleton_pattern

类似的, CI_Controller::get_instance()->$className->$method(); 这看起来好像更多的键入您所请求的CI()->$className->$method

最终,要求只能创build一个$instance ,然后通过引用来分配的需求将被消除。

PHP4不支持方法链接,最近CI2.0.0版)放弃了对PHP4支持。 编写$CI比每次写get_instance()都容易。

它可能是几件事情的组合,包括已经提到的:

  • 向后兼容
  • 方便
  • 时尚指南

最好,我喜欢把这个“推荐”的想法作为风格指南的一部分。 也许不是CI的官方风格指南,但仍然。

想象一下,CI的所有第三方脚本都实现了这个build议,任何开发者都能够快速确定这些脚本是如何devise的 – 尽pipe这只是脚本的一小部分。

另外一个重要的事情就是方法链的机制 – 做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(); } } 

从PHP5开始,通过引用获取get_instance()的结果是毫无意义的。 不幸的是,这种坏习惯似乎根深蒂固,所以让我们来处理。

对于那些感兴趣的,这里是一个快速实例getter:

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

请注意,如果通过引用分配静态variables将不起作用。

另外,你不得不通过引用这个CI()的结果CI() 。 额外的糖:-)

啊,显然你仍然有这个函数调用的(轻微)成本。 你仍然可能想要使用一个variables,而不是调用函数几十次。