web-dev-qa-db-ja.com

Codeigniterのget_instance():なぜ変数に割り当てるのですか?

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スーパーオブジェクトを返します。

通常、コントローラー関数内から、_$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オブジェクトを使用できます。

関連記事: explain $ CI =&get_instance(); / Codeigniter:Get Instance

だから、ここに私の実際の質問があります:

ユーザーガイドが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オブジェクト全体をクラス変数に割り当てるようなseemsは、たとえそれが参照であっても素晴らしいアイデアではありません。多分それは問題ではありません。

入力しやすいようにget_instance()のラッパー関数を作成したいので、常に変数に割り当てる必要はありません。

_function CI()
{
    return get_instance();
}
_

または:

_function CI()
{
    $CI =& get_instance();
    return $CI;
}
_

そうすれば、変数に代入する手間をかけずにどこからでもCI()->class->method()を使用でき、変数の内容を非常に簡単に記述して理解でき、より短く、よりエレガントなコードを作成できます。

  • このアプローチを取らない理由はありますか?
  • 上記の2つのCI()関数に違いはありますか?
  • get_instance()を直接呼び出すのではなく、変数に割り当てることが推奨されるのはなぜですか?
  • function &get_instance(){}の_&_は、それがどこで定義されているのですか? references の目的について少し知っているので、必要に応じて使用しますが、この方法で定義された関数を見たことはありません。ラッパー関数を作成する場合、これも使用する必要がありますか?

これはstyleの質問ではなく、技術的な質問であることに注意してください。私が提案している方法を使用して、問題、パフォーマンスまたはその他があるかどうかを知りたいです。

[〜#〜] edit [〜#〜]:これまでのところ:

  • メソッドチェーンはphp4では使用できないため、変数への割り当ては回避策です(ただし、Codeigniterはphp4サポートを削除しているため、これはかなり無関係です)
  • 関数を1回呼び出して変数に割り当てるのではなく、関数を複数回呼び出してオブジェクトを返すという小さなオーバーヘッド。

他に何か、またはこれらが唯一の潜在的な問題ですか?

58
Wesley Murch

私の知る限り、それは何よりも利便性の問題です。ライブラリでCIスーパーオブジェクトを頻繁に使用する可能性があるので、それを変数に割り当てて、作業を少し簡単にするのはなぜですか?

他にも考慮すべきことがいくつかあります...

  1. このメソッドをヘルパーに入れると、そのメソッドは使用しているクラスの依存関係になります。これは大したことではないかもしれませんが、ライブラリを他の人と共有したい場合、彼らは満足しません。特にCIコミュニティでこれを処理する標準的な方法がすでにあるためです。
  2. 結果を変数に保存するのではなく、ヘルパーを使用するたびにget_instance()を呼び出すため、パフォーマンスにわずかな影響があります。
  3. これは時間を節約するためのヘルパーメソッドであるため、CIのコアMVCファイルで主に作業している人にとっては、このようなヘルパーのセットアップは、必要ないくつかの場所で変数に設定するよりも時間がかかりますそれ。
22
Chris Schmitz

_CI_Controller::$instance_の値は、クラスの別のインスタンスが作成されると変更される可能性があるため、参照によって割り当てる必要があります。コンストラクターは、実行するたびに_self::$instance_を再割り当てします。

一般的に、これは悪いデザインパターンのように感じられ、クラスを1つのインスタンスのみに制限するシングルトンのプロパティ http://en.wikipedia.org/wiki/Singleton_pattern が欠落しています。

CI_Controller::get_instance()->$className->$method();と入力できるようです。これは、要求されたCI()->$className->$methodよりも入力が多いようです。

最終的に、_$instance_のインスタンスを1つだけ作成し、参照による割り当ての必要性を排除することを要求することは理にかなっています。

3
Ben

直接呼び出すのではなく、変数にget_instance()を割り当てることが推奨されるのはなぜですか?

最も可能性が高いのは、php4との後方互換性を維持することをお勧めします。php4では、デフォルトではオブジェクトは参照渡しではなく、複製されています。

このアプローチを取らない理由はありますか?

古いPHPインストールでアプリケーションを実行する場合のみ

3

メソッドチェーンは_PHP4_ではサポートされておらず、CIは最近(バージョン_PHP4_から)_2.0.0_のサポートを終了しました。また、毎回get_instance()と書くよりも_$CI_と書くのは簡単です。

3
Muhammad Usman

私はこの方法を使うことを好みます、それは簡単です

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

既に述べたものを含む、いくつかのことの組み合わせである可能性があります。

  • 下位互換性
  • 便利さ
  • スタイルガイド

できれば、この「推奨」がスタイルガイドの一部であるという考えが好きです。 CIの公式スタイルガイドではないかもしれませんが、まだです。

CIのすべてのサードパーティスクリプトがこの推奨事項を実装していることを想像してください。開発者は、これらのスクリプトがどのように設計されているかをすぐに判断できます。

IMOが重要なもう1つのことは、メソッドチェーンの仕組みです。そして、CI()->class->method()を行うことは、CIの残りの部分がどのように機能するかを知っているため、直感的ではありません。

1
Repox

参照によってget_instance()の結果を取得することは、PHP5以降では意味がありません。悲しいことに、この悪い習慣は根が深いようですので、対処しましょう。

興味のある方のために、ここに超高速のインスタンスゲッターがあります。

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

    return $CI;
}
_

参照によって割り当てられた場合、静的変数は機能しないことに注意してください。

また、このCI()の結果を参照によって取得しないように強制されます。余分な砂糖:-)

ああ、明らかにあなたはまだ関数呼び出しの(わずかな)コストを持っています。関数を何十回も呼び出す代わりに、変数を使用したい場合があります。

0
Gras Double