php Codeigniter 中的 get_instance():为什么将其分配给变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7195544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:14:35  来源:igfitidea点击:

get_instance() in Codeigniter: Why assign it to a variable?

phpcodeignitersingletonreference

提问by Wesley Murch

In Codeigniter, get_instance()is a globally available function that returns the Controller super-object which contains all the currently loaded classes (it returns the Controller class instance). I'll include the current source code:

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

get_instance()is defined in Codeigniter.php

get_instance()定义在 Codeigniter.php

// Load the base controller class
require BASEPATH.'core/Controller.php';

function &get_instance()
{
    return CI_Controller::get_instance();
}

And CI_Controlleris defined in Controller.php

并且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;
    }
}

Here's how it is recommended to be used in the user guide for creating libraries:

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

Utilizing CodeIgniter Resources within Your Library

To access CodeIgniter's native resources within your library use the get_instance()function. This function returns the CodeIgniter super object.

Normally from within your controller functions you will call any of the available CodeIgniter functions using the $thisconstruct: $this->load->helper('url'); $this->load->library('session'); $this->config->item('base_url');etc.

$this, however, only works directly within your controllers, your models, or your views. If you would like to use CodeIgniter's classes from within your own custom classes you can do so as follows:

First, assign the CodeIgniter object to a variable:

$CI =& get_instance();

Once you've assigned the object to a variable, you'll use that variable instead of $this: $CI =& get_instance(); $CI->load->helper('url'); $CI->load->library('session'); $CI->config->item('base_url'); etc.

Note: You'll notice that the above get_instance()function is being passed by reference:

$CI =& get_instance();

This is very important.Assigning by reference allows you to use the original CodeIgniter object rather than creating a copy of it.

在您的库中使用 CodeIgniter 资源

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

通常在您的控制器函数中,您将使用$this结构调用任何可用的 CodeIgniter 函数: $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->helper('url'); $CI->load->library('session'); $CI->config->item('base_url'); 等等。

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

$CI =& get_instance();

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

Related posts: explain $CI =& get_instance();/ Codeigniter: Get Instance

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

So, here is my actual question:

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

Why does the user guide recommend assigning get_instance()to a variable? I'm fairly certain I understand the implications of not assigning by reference, but why is it recommended to assign it to a variable when get_instance()->load->model()works fine?

为什么用户指南建议分配get_instance()给变量?我相当肯定我理解不通过引用分配的含义,但是为什么建议在get_instance()->load->model()工作正常时将其分配给变量?

I see a lot of user defined or third party classes in CI that assign to a property of the object:

我在 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');
    }
}

Poor example, but I see this frequently. Why bother with this method instead of just calling get_instance()directly? It seemslike assigning the entire Controller object to a class variable wouldn't be a great idea, even if it is a reference. Maybe it doesn't matter.

不好的例子,但我经常看到这个。为什么要麻烦这个方法而不是get_instance()直接调用?它看起来像分配整个控制器对象类变量不会是一个伟大的想法,哪怕是一个参考。也许没关系。

I want to write a wrapper function for get_instance()so it's easier to type, and I don't have to constantly assign it to a variable.

我想为它编写一个包装函数,get_instance()以便更容易输入,而且我不必经常将它分配给一个变量。

function CI()
{
    return get_instance();
}

Or:

或者:

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

Then I could use CI()->class->method()from anywhere without the hassle of assigning it to a variable, it's very easy to write and understand what it does, and can result in shorter, more elegant code.

然后我可以CI()->class->method()在任何地方使用而无需将它分配给变量,编写和理解它的功能非常容易,并且可以产生更短、更优雅的代码。

  • Is there any reason not to take this approach?
  • Is there any difference between the two CI()functions above?
  • Why is it recommended to assign get_instance()to a variable rather than calling it directly?
  • What does the &in function &get_instance(){}mean where it is defined? I know a bit about what referencesare for and I use them when appropriate, but I've never seen a function defined this way. If I do write a wrapper function, should I use this as well?
  • 有什么理由不采取这种方法吗?
  • CI()上面两个函数有什么区别吗?
  • 为什么推荐给get_instance()一个变量赋值而不是直接调用它?
  • &infunction &get_instance(){}在定义的地方是什么意思?我对引用的用途有所了解,并在适当的时候使用它们,但我从未见过以这种方式定义的函数。如果我确实编写了一个包装函数,我是否也应该使用它?

Please note that this is not so much a stylequestion, but a technical one. I want to know if there are any issues, performance or otherwise, with using the method I'm suggesting.

请注意,这与其说是一个风格问题,不如说是一个技术问题。我想知道使用我建议的方法是否存在任何问题、性能或其他问题。

EDIT: So far we have:

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

  • Method chaining is not available in php4, so assigning to a variable is a workaround (although this is fairly irrelevant as Codeigniter has dropped php4 support)
  • The minor overhead of calling a function more than once to return the object, rather than calling it once and assigning to a variable.
  • 方法链在 php4 中不可用,因此分配给变量是一种解决方法(尽管这与 Codeigniter 已放弃对 php4 的支持无关)
  • 多次调用函数以返回对象的较小开销,而不是调用一次并分配给变量。

Anything else, or are these the only potential issues?

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

采纳答案by Chris Schmitz

As far as I know, it's a matter of convenience more than anything. Chances are that you will be using the CI super object a lot in your libraries so why not assign it to a variable to make it a little easier to work with?

据我所知,这比什么都重要。您可能会在库中大量使用 CI 超级对象,那么为什么不将其分配给一个变量以使其更易于使用呢?

There are a few other things to consider...

还有一些其他的事情需要考虑......

  1. If you put this method in a helper, that method becomes a dependency for any class you are using it in. This might not be a big deal for you, but if you want to share libraries with anyone else they may not be happy about the dependency, especially since there is already a standard way of handling this in the CI community.
  2. There is a slight impact on performance because you are calling get_instance()every time you use the helper rather than storing its result in a variable.
  3. Since this is a helper method that is supposed to save you time, for anyone who is working mostly in the core MVC files of CI, setting up a helper like this would take longer than just setting it to a variable in the few places you need it.
  1. 如果您将此方法放在帮助程序中,该方法将成为您在其中使用它的任何类的依赖项。这对您来说可能不是什么大问题,但是如果您想与其他人共享库,他们可能会对依赖,特别是因为在 CI 社区中已经有一种标准的方法来处理这个问题。
  2. 对性能有轻微影响,因为您get_instance()每次使用帮助程序时都会调用,而不是将其结果存储在变量中。
  3. 由于这是一种可以节省您时间的辅助方法,对于主要在 CI 的核心 MVC 文件中工作的任何人来说,设置这样的辅助方法比仅在您需要的几个地方将其设置为变量需要更长的时间它。

回答by dev-null-dweller

Why is it recommended to assign get_instance() to a variable rather than calling it directly?

为什么建议将 get_instance() 分配给变量而不是直接调用它?

Most probably, it is recommended to maintain backward compatibility with php4, where objects were not passed by reference by default, but were cloned.

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

Is there any reason not to take this approach?

有什么理由不采取这种方法吗?

Only if you want your application to run on outdated php installations

仅当您希望您的应用程序在过时的 php 安装上运行时

回答by Muhammad Usman

Method chaining is not supported in PHP4and CIdropped support for PHP4very recently (from version 2.0.0). Also it's easy to write $CIthan writing get_instance()every time.

方法链在最近(从 版本)中不受支持PHP4CI放弃了支持。而且写起来比每次都写容易。PHP42.0.0$CIget_instance()

回答by Ben

It is necessary to assign by reference because the value of CI_Controller::$instanceis subject to change if another instance of the class is created. The constructor re-assigns self::$instanceeach time it runs.

必须通过引用分配,因为CI_Controller::$instance如果创建了另一个类的实例, 的值可能会发生变化。构造函数self::$instance每次运行时都会重新分配。

In general, this feels like a bad design pattern and is missing the property of a singleton that limits the class to only one instance, http://en.wikipedia.org/wiki/Singleton_pattern.

一般来说,这感觉像是一种糟糕的设计模式,并且缺少将类限制为一个实例的单例属性,http://en.wikipedia.org/wiki/Singleton_pattern

It seems possible to type, CI_Controller::get_instance()->$className->$method();which does seem like more typing that your requested CI()->$className->$method.

似乎可以输入,CI_Controller::get_instance()->$className->$method();这似乎比您要求的输入更多CI()->$className->$method

Ultimately, it would make sense to require that only one instance of $instancecan be created and then the need for assigning by reference would be eliminated.

最终,要求只能$instance创建一个实例是有意义的,然后通过引用分配的需要将被消除。

回答by user2604283

I prefer uses this way, it's simple

我更喜欢用这种方式,很简单

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();
    }
}

回答by Repox

It could be a combination of several things, including the already mentioned:

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

  • Backwards compatibility
  • Convenience
  • Style Guide
  • 向后兼容
  • 方便
  • 时尚指南

Preferably, I like the idea of this 'recommendation' as being a part of a style guide. Maybe not the official style guide of CI, but still.

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

Imagine that all third-party scripts for CI implements this recommendation, any developer would be able to quickly determine how these scripts are designed - although this just being a very small part of the script.

想象一下,CI 的所有第三方脚本都实现了这个建议,任何开发人员都能够快速确定这些脚本是如何设计的——尽管这只是脚本的一小部分。

Another thing that IMO is important is the mechanics of method chaining - and doing CI()->class->method()wouldn't seem intuitive for me, knowing how the rest of CI works.

IMO 重要的另一件事是方法链的机制 -CI()->class->method()对我来说,这样做似乎并不直观,因为我知道 CI 的其余部分是如何工作的。

回答by Gras Double

Getting the result of get_instance()by reference just makes no sense since PHP5. Sadly this bad habit seems to be deep-rooted, so let's just deal with it.

get_instance()从 PHP5 开始,通过引用获取结果毫无意义。可悲的是,这个坏习惯似乎根深蒂固,所以让我们解决它。

For those interested, here's an über fast instance getter:

对于那些感兴趣的人,这是一个超级快速的实例获取器:

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

    return $CI;
}

Note that the static variable wouldn't work if it were assigned by reference.

请注意,如果静态变量是通过引用分配的,则它不起作用。

Also, you are forced not to get by reference the result of this CI(). Extra sugar :-)

此外,您被迫不通过引用获取 this 的结果CI()。额外的糖:-)

Ah, and obviously you still have the (slight) cost of the function call. You still may want to use a variable instead of calling the function dozens of times.

啊,显然你仍然有函数调用的(轻微)成本。您可能仍然希望使用变量而不是多次调用该函数。