web-dev-qa-db-ja.com

他のモデルのCodeIgniterモデルへのアクセス

以前は、CodeIgniterモデル内では別のモデルにアクセスできませんでした。

$this->load->model('bar');
$this->bar->something();

これはまだ有効ですか、それとも変更しましたか?

38
Click Upvote

これらは、簡単な質問に対する非常に長い回答です。

短い答え:これは完全にサポートされるようになりました。気分が良ければクロスロード!

69
Phil Sturgeon

「モデル」はデータベーステーブルを単純なCRUD操作でのみカプセル化する必要があるという考えに強く反対します。ウィキペディアの記事で述べたように:

http://en.wikipedia.org/wiki/Model-view-controller#As_a_design_pattern

...そのアプリケーション層は、単に単一のデータベーステーブル抽象化として機能するだけではありません。 「コントローラー」という言葉の意味について考えてみてください。「コントローラー」は、それ自体がアプリケーション全体ではなく、ディレクターとして機能する必要があります。 「モデル」は、ビジネスロジックの場所です。実際、ほとんどの大規模アプリケーションは、ビジネスロジックの多くをデータベース自体に保持しています(トリガー、ストアドプロシージャ、外部キーなどの形で)。

「モデル」が何であるかについての誤解は、概念自体をあまり理解せずに、「MVC」の同じ(過剰)誇大宣伝に一部起因していると思います。 "AJAX"がいかに空であるか、またはさらに簡単な "Web 2.0"が好きです。良くも悪くも、多くのスクリプトキディがMVCワゴンに飛びついています。単純なハウツーやサンプルシナリオでは、データベースコードを「モデル」に配置するように指示するだけなので、そのレイヤーの誤用はデータベースの抽象化だけが当たり前になっています。これで、インターネット上で「unpure」、「dirty」、「hackish」と呼ばれる投稿を読んで、ビジネスロジックをモデルに配置しました。それは間違っている。誤解。

簡単な例は、外部キーについて考えることです。「モデル」だけをdatabaseモデルにしたい場合でも、「純粋」にしたい場合"、"正しい "またはあなたが何を持っているか、あなたは本当にそこに参照整合性を強制するべきです。 MySQLには長年にわたって実際の外部キーのサポートがなかったため、Webアプリケーションは、参照整合性についてまったく心配することなく成長しました。私が推測するスクリプトキディライフスタイルに適合します。とにかく、モデルのこの簡略化されたビューでも外部キーの有効性を維持できるようにするには、モデルを他のモデルと連携させる必要があります(または、特にCodeIgniterのようなフレームワークではそうできない場合は、他のモデルにクエリを記述する必要がありますテーブル、時々他の場所でクエリを複製する-それは悪いスタイルです)。

したがって、これはCodeIgniterの欠点だと思います。それは簡単な修正ではないかもしれませんが、それは確かに残念な見落としです。

だから私がやったことは上記のサンプルコードを取り、それをヘルパーに抽象化して、通常の$ this-> load-> model()機能とほぼ同じように機能する関数を手に入れることでした。ここにあります(自動ロードされるヘルパーに入れて、どのモデルでも使用できます):


   /**
    *
    * Allow models to use other models
    *
    * This is a substitute for the inability to load models
    * inside of other models in CodeIgniter.  Call it like
    * this:
    *
    * $salaries = model_load_model('salary');
    * ...
    * $salary = $salaries->get_salary($employee_id);
    *
    * @param string $model_name The name of the model that is to be loaded
    *
    * @return object The requested model object
    *
    */
   function model_load_model($model_name)
   {
      $CI =& get_instance();
      $CI->load->model($model_name);
      return $CI->$model_name;
   }
39
oribani

それは可能ですが、理想的ではなく、悪いと考えられており、理想的または純粋な実装よりも「迅速な修正」の方が多くなります。

class Location extends Model{
      public function get($ID){
                // Get main CI object handle and load model
                $CI =& get_instance();
                $CI->load->model('LocationType');
                // Call new model functions using handle to main CI object
                $CI->LocationType->setID($result->LocationTypeID);
                $CI->LocationType->setTitle($result->TypeTitle);
                $this->_locationType = $CI->LocationType;
                //Other Stuff
    }
}

このようなメインCIオブジェクトを使用しているときはいつでも、おそらく悪い考えです。レイアウトを再考して、コントローラーとモデル間でデータをやり取りしてください。

http://codeigniter.com/forums/viewthread/69833/

8
MECU

Phil Sturgeonが言うようにモデルからモデルをロードできますが、モデルコンストラクターでモデルをロードする場合は、依存関係に注意する必要があります。モデルAがモデルBを使用し、モデルBがモデルAを使用する場合、1つまたはその他、無限ループに入ります。

6
Dave Meybohm

このようなCode Igniterの状況では、次の2つの可能性のいずれかを優先します。

1)モデルの属性とセッターを次のようにします:

class X extends Model {
  var $Y_model;
  public function setY($Y) {
    $this->Y_model = $Y;
  }

  public function doItRightNow($a,$b) {
    $list = $this->Y_model->getSomeList($a,$b);
    // ...
  }
  // ...
}


次に、他のメソッドの前にこのセッターを使用して、他のモデルのインスタンスを与え、メソッドで使用できるようにします。

$this->load->model('X');
$this->load->model('Y');
$this->X->setY($this->Y);
$this->X->doItRightNow($something,$somethingElse);



2)コントローラーから他のモデルインスタンスを与えるメソッドにパラメーターを持たせる。

class X extends Model {
  public function doItRightNow($a,$b,$Y_model) {
    $list = $Y_model->getSomeList($a,$b);
    // ...
  }
  // ...
}

次のように使用します。

  $this->load->model('X');
  $this->load->model('Y');
  $this->X->doItRightNow($something,$somethingElse,$this->Y);



これらはよりクリーンな可能性だと思います。
どの方法を使用するかは、他のモデルにアクセスするために必要なメソッドの数によって異なります。 1つまたは2つある場合は、メソッドパラメータとして指定することをお勧めします。もしもっとあれば-クラス属性とセッターを持つほうがいいと思います。
そして、いくつかの条件に応じてエレガントな方法でモデルを与えることができます-両方が同じ種類のデータが返される同じインターフェイスを部分的に実装している場合(ほとんど役に立ちませんが、場合によってはそれが可能です)。

1
Zbyszek

モデルにアクセスし、必要に応じてライブラリをモデルに含める方が、一般的には書き込みライブラリの方が良いと思います。

たとえば、誰かが特定のCRUDアクションを実行することを許可されているかどうかを確認する必要がある場合、使用している認証ライブラリを含めることができます(ほとんどの場合、ライブラリは自動で含められます)。必ずしもモデルに直接アクセスする必要はありません。単に汚くて不適切なようです。

コントローラーで行う必要があることを実行し、必要に応じて1つのモデルのメソッドからの結果を他のモデルのメソッドに渡すことをお勧めします。

それにもかかわらず、あるモデルを別のモデルに組み込むこと自体がなぜ不可能であるのか、私にはわかりません。しかし、あなたが示している構文でそれを行うことはできないと思います。他の複雑な方法で行う必要があります。いずれにせよ、IMO、モデルを別のモデルに直接含めることは悪い習慣です。

0
KyleFarris

CI 2.0では、1つのモデルを別のモデルから直接呼び出すことができます。

0
phirschybar