3

私はここ数ヶ月 Yii をいじっていますが、コードを Yii のように構造化するために、モデルを他のモデルのリストにするのに最適な方法を考えていました。

Yii は概念的に DAO に非常に近いモデルを持っているようですが、MVC の設計では非 DAO モデルをモデル以外の場所に置かないようにしています。(私は MVC の専門家ではありません)

2 つの理由、リストが優れている:

  • リレーションで取り組むことができないかなりの量のロジックを持つオブジェクトがある場合に拡張するCModelListのようなものを探しています(とにかくCActiveRecord要素です)
  • 型としてのリストは、要素にロジックを適用できますが、それらすべてを一度にメモリにロードする必要はなく、ID を使用してコード全体で操作できる単一の型を提供し、サブセットのみをロードします。

問題を解決していないように見えるもの

  • Relational Active Record : すべてのモデルがアクティブ レコードであるとは限らないため
  • CAttributeCollection : 配列のようなメモリ内のすべてのオブジェクトのみをサポートするため
  • getRestaurantsAverageRatingByPriceRange などの異なるモデル内の同じメソッド: モデルがより多くのメソッドを持っているため、OOP 内の関数型プログラミングが急速に成長しているためです。

例 1

$user = User::model()->findByPk($userID);  // get a user
$restaurantList = $user->getRestaurants(); // get restaurants for that user

for($i=0;$i<5;$i++) {
   $this->renderPartial( "rating", 
      array("rating" => $restaurantList->getAverageRatingByPriceRange( $i ) );
}  

例 2 (同じリスト ロジック、異なる基本モデル)

$city = City::model()->findByPk($cityID);  // get a city
$restaurantList = $city->getRestaurants(); // get restaurants for that city

for($i=0;$i<5;$i++) {
   $this->renderPartial( "rating", 
      array("rating" => $restaurantList->getAverageRatingByPriceRange( $i ) );
}  

例 3 (同じリスト タイプと基本モデル、異なるロジック)

$user = User::model()->findByPk($userID);  // get a user
$restaurantList = $user->getRestaurants(); // get restaurants for that user


$this->renderPartial( "map", 
   array("coord" => $restaurantList->getCoordinatesMap() );

Yii にはそれが欠けているのでしょうか、別の考え方を始めるべきでしょうか、それともクリーンなコードと構造を使用して維持するためのメカニズムは何ですか?

4

1 に答える 1

2

コンポーネント動作の使用

コンポーネントはミックスインパターンをサポートし、1 つまたは複数の動作に関連付けることができます。ビヘイビアとは、特殊化 (つまり、通常のクラス継承) ではなく機能を収集する手段を通じて、接続されたコンポーネントによってメソッドを「継承」できるオブジェクトです。コンポーネントは複数の動作に関連付けることができるため、「多重継承」を実現できます。

動作クラスはIBehaviorインターフェイスを実装する必要があります。ほとんどの動作は、CBehavior基本クラスから拡張できます。動作をモデルに関連付ける必要がある場合は、モデル固有の追加機能を実装するCModelBehaviorまたはCActiveRecordBehaviorから拡張することもできます。

ビヘイビアを使用するには、ビヘイビアのattach()メソッドを呼び出して、最初にコンポーネントにアタッチする必要があります。次に、コンポーネントを介してビヘイビア メソッドを呼び出すことができます。

// $name uniquely identifies the behavior in the component
$component->attachBehavior($name,$behavior);
// test() is a method of $behavior
$component->test();

添付された動作は、コンポーネントの通常のプロパティのようにアクセスできます。たとえば、tree という名前のビヘイビアがコンポーネントにアタッチされている場合、次を使用してこのビヘイビア オブジェクトへの参照を取得できます。

$behavior=$component->tree;
// equivalent to the following:
// $behavior=$component->asa('tree');

コンポーネントを介してメソッドを使用できないように、動作を一時的に無効にすることができます。例えば、

$component->disableBehavior($name);
// the following statement will throw an exception
$component->test();
$component->enableBehavior($name);
// it works now
$component->test();

同じコンポーネントに関連付けられた 2 つの動作が同じ名前のメソッドを持っている可能性があります。この場合、最初にアタッチされたビヘイビアのメソッドが優先されます。

eventsと一緒に使用すると、動作はさらに強力になります。ビヘイビアーは、コンポーネントにアタッチされると、そのメソッドの一部をコンポーネントのイベントにアタッチできます。そうすることで、動作はコンポーネントの通常の実行フローを観察または変更する機会を得ます。

ビヘイビアーのプロパティには、アタッチされているコンポーネントからもアクセスできます。プロパティには、パブリック メンバー変数と、動作のゲッターやセッターを介して定義されたプロパティの両方が含まれます。たとえば、動作に xyz という名前のプロパティがあり、その動作がコンポーネント $a に関連付けられているとします。次に、式$a->xyzを使用して動作のプロパティにアクセスできます。

詳細:
http://www.yiiframework.com/wiki/44/behaviors-events
http://www.ramirezcobos.com/2010/11/19/how-to-create-a-yii-behavior/

于 2012-06-20T06:34:34.287 に答える