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_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; } }
以下是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而不是直接调用? -
&
infunction &get_instance(){}
是什么意思? 我知道一些关于什么是引用是适用的,但我从来没有见过这样定义的函数。 如果我写封装函数,我也应该使用它?
请注意,这不是一个风格问题,而是一个技术问题。 我想知道是否有任何问题,performance或其他 ,使用我build议的方法。
编辑 :到目前为止我们有:
- 方法链接在php4中不可用,因此分配给variables是一种解决方法(尽pipe这与Codeigniter已经减less了对php4的支持是毫不相关的)
- 多次调用一个函数来返回对象的次要开销,而不是调用一次并分配给一个variables。
还有什么,或者这是唯一的潜在问题?
据我所知,这是一个比任何事情都方便的问题。 有可能你会在你的库中使用CI超级对象,为什么不把它分配给一个variables,使它更容易处理?
还有其他一些事情要考虑…
- 如果你把这个方法放在帮助器中,那么这个方法就会成为你使用它的任何类的依赖。这对你来说可能不是什么大问题,但是如果你想和其他人共享库,他们可能不会很高兴依赖,特别是因为在CI社区中已经有了一个标准的处理方法。
- 对性能有轻微的影响,因为每次使用助手时都要调用
get_instance()
,而不是将结果存储在variables中。 - 由于这是一个帮助你节省时间的方法,对于那些主要在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
不支持方法链接,最近CI
( 2.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,而不是调用函数几十次。