2012-04-02 13 views
7

したがって、CGridViewに、組織のニーズに合わせて高度な検索機能を追加しました。Yii - 高度な検索を使用したカスタムCGridViewのクエリ操作

  • フィルター - あなたがテーブルに/非表示の列を表示することができます、そしてあなたはまた、各項目の左に少しドラッグアイコンをドラッグして列の順序を変更することができます。
  • 並べ替え - 複数の列を選択することができます。昇順または降順を指定します。
  • 検索 - 列を選択し、検索パラメータを挿入します。選択した列のデータ型に合わせた演算子。

Advanced Search Screenshot

バージョン1つの作品、ゆっくりとはいえ。基本的にはの内部動作を手に入れました。ここではDataProviderの結果を取得し、テーブルの内容をレンダリングする前にPHPで検索とソートを行います。

バージョン2では、巧妙なCDbCriteriaの作成に集中することを目指しています。これにより、MySQLは重い作業を行うので、より速く実行できます。単一のデータベーステーブルを扱う場合、実装は簡単です。 2つ以上のテーブルを扱っているときに問題が発生する...例えば、ユーザがSTATの関係を検索しようとしている場合、その関係がクエリに含まれている必要があります。 。

ここに質問があります。どのようにしてYiiにすべてのwithリレーションがクエリに含まれていることを確認して比較を含めることができますか?私はすべての関係withモデルのsearch機能で自分の基準を含めましたし、私がために、

その後
public function search() { 
    $criteria=new CDbCriteria; 
    $criteria->compare('id', $this->id); 
    $criteria->compare(... 
    ... 
    $criteria->with = array('relation0','relation1','relation3'); 
    $criteria->together = true; 

    return new CActiveDataProvider(
     get_class($this), array(
      'criteria'=>$criteria, 
      'pagination' => array('pageSize' => 50) 
));} 

私はDataProvideradd a few conditionsから基準を奪うよ... trueにCDbCriteriaのtogetherセットを試してみましたたとえば、1234567890>日付を探しているしかし、私はまだこのようなエラーが発生します...

relation0relation1はここで、depicte BELONGS_TO関係が、どの STAT関係している
CDbCommand failed to execute the SQL statement: 
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.relation3' in 'where clause'. 
The SQL statement executed was: 
SELECT COUNT(DISTINCT `t`.`id`) FROM `table` `t` 
LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
WHERE (`t`.`relation3` > 1234567890) 

dがrelation3となっています。さらに、クエリはなぜSELECT COUNT(DISTINCT 't'.'id')ですか?

編集 @DCoderここでは、私が今作業している特定の関係について説明します。メインテーブルはCallで、CallSegmentsとの関係はHAS_MANYであり、時刻は保持されます。したがって、コールのstartTimeは、関連するすべてのCallSegmentsの最小開始時間です。そしてstartTimeは私の匿名化されたクエリエラーで仮想のrelation3です。

'startTime' => array(self::STAT, 'CallSegments', 'call_id', 
      'select' => 'min(`start_time`)'), 

編集他の人々はCDbCriteria's together propertyに私を送ってきていますが、上記を参照できるように、私は現在、無駄にそれをしようとしています。Yiigithubチケット:

編集が報告されていることがありました問題のように見えます。

+1

さらに関連するコード、具体的にはモデルのリレーション宣言を表示できますか? STATリレーションは通常、別々のクエリとして実行されます。 – DCoder

+0

Alright @DCoder、私は今働いている関係を追加しました。あなたはもっと欲しいですか?クエリにSTAT関係を含める方法はありますか?私はそれがCDbCriteriaが一緒だったのだが、明らかにそうではないと思った。 –

+0

あなたの匿名化されたrelation0、relation1およびrelation3が何であるかはまだ分かりませんが、私は、一時テーブルにcall_idとmin(start_time)を選択し、STATに頼るのではなくそのテーブルに参加する必要があると思います。データベースエンジンが計算カラムをサポートしていれば、それはまともな選択肢です。 – DCoder

答えて

2

基準からSQLを取得して自分で使用することはお勧めしません。あなたは、あなたが簡単のような比較を使用することができます「と」プロパティを使用している場合

$criteria->compare("`relation1`.`id`", $yourVarHere); 

もYiiは、グループ化とうまく動作しません。 STAT関係と

私のアプローチがあるが続くのYiiの選択でサブクエリを、使用している:

$criteria->select = array("`t`.*", "(SELECT COUNT(*) FROM `relation3` WHERE `id` = `t`.id_relation3) AS `rel3`"); 
$criteria->having = "`rel3` > " . $yourValue; 

カウントが別のクエリで行われるため、上記の方法は、GridViewのページネーションのバグを作成します。バグがあなたのようにSTAT関係を使用することができます作業を取得することはほとんど困難である場合

$criteria->join = "LEFT OUTER JOIN `relation_table` `relation0` ON (`t`.`id`=`relation0`.`id`) 
LEFT OUTER JOIN `relation_table` `relation1` ON (`t`.`id`=`relation1`.`id`) 
LEFT OUTER JOIN `relation_table` `relation3` ON (`t`.`id`=`relation3`.`id`)"; 
0

:この問題を回避するには、プロパティ「で」ドロップなど「参加」プロパティに自分で加入書くことになりますシンプルなHAS_ONE:

'select'=>'count(relation3.id)', 
'joinType'=>'left join', 
'group'=>'relation3.id', 
'on'=>'t.id = relation3.id', 
'together'=>true 

他のすべての面でカウント値を取得するには?

これはあなたのケースではどれくらいうまくいくのかよく分かりませんが、時々私が役に立ちました。

関連する問題