「しゅごいねー」は不朽の名作『赤ちゃんと僕』のミノル君からパクりました。

YiiにはName Scopeという便利機能があります。
cakeとかSymfonyにもあるのかな?Railsからパクったらしいです。
例えば

class model
{
	public function scopes()
	{
		return array(
			'scope1'=>array(
				'condition'=>'status=:status',
				'params'=>array(':status'=>'public',
				'order'=>'created',
			),
			'scope2'=>array(
				'limit'=>10,
			),
		);
	}

こんな感じで設定しておけば、

$models = $model->scope1()->scope2()->findAll();

上記みたく書いたらscope1の条件とかscope2のlimitが反映されて検索してくれる。
さらに、リレーション時にも使えて

$model->scope1->with('comment:scope3')->findAll();

こんな感じでリレーションcommentで使うmodelにscope3が設定されてると、それが反映されて以下略、みたいな。

このName Scopeの素晴らしさはそれだけではなく、引数も扱えるんですよ。

class model{
	function scopeHoge( $category ){
		$this->getDbCriteria()->mergeWith(array(
			'condition'=>'category='.$category,
		));
		return $this;
	}

これで下記のように書けばcateogryが3のモノを取ってくる。

$model->scopeHoge(3)->findAll();

便利ですよね。
思わずRails先生の方向いて手をあわせました。

でも一個だけ弱点があって。。。
引数を取れる関数バージョン時とリーレションでの適用を同時に使えないんですよ。

$model->scope1()->with('comment:scopeHoge(3)')->findAll();

いや、引数取れないんだしいいじゃん!って話もあるんですけどね。
リレーションで使うName Scopeは素直にscopes関数で設定してあげましょう。
出来れば命名規則(プリフィックスでscopeとか)でもいいから関数対応してほしいナ。

あと、注意点としてwith()の返り値はmodel(CActiveRecode)じゃなくてCActiveFinderという別モノなので、with()からNameScopeにはチェイン出来ません。
かならず『モデル->スコープ->with->find』という流れにするように気を付けましょう(・∀・)コレで10分ハマッタ!

関連する記事

  1. behaviorためしてみた Yii Framework触るぜ日記(4)
  2. ヨッパゲついでに小話2 Yii Framework触るぜ日記(9)