CakePHPで検索条件を入力してページング処理を行うことはわりとよくあると思うけど、その際、検索条件が複数あり、そして条件によってOR検索やAND検索を組み合わせて使わなければいけない場合も結構あるのではないかと思う。
これが最適なやり方かどうかは自分でも分からないけれど、いくつかのパターンをここにメモっておこうと思う。
AND検索のみの場合
ANDのみの場合はそんなに難しくはない。全ての条件を配列にぶっこんでやればOK。
面倒なのでテーブルの中身とかは一切書かないけど、ここではname(名前)とage(年齢)というカラムがあって、その中から名字が佐藤さんで年齢が20歳以上のデータをAND検索するとしよう。モデル名はUser。
$conditions[] = array('User.name' => '佐藤', 'User.age >=' => '20');
$this->paginate('User', $conditions);
//SQLのWHERE句の部分
WHERE User.name = '佐藤' AND User.age >= '20'
WHERE句のところはちょっと適当に書いたけど、たぶん出力結果はこんな感じで合ってると思う。
OR検索のみの場合
OR検索のみも、まあ別に難しくはないと思う。
では、上記と同じようなテーブルがあるとして、今回は名字が佐藤さんか中村さんのデータをOR検索する場合。
$conditions['OR'] = array('User.name' => array('佐藤', '中村'));
$this->paginate('User', $conditions);
//SQL
WHERE User.name = '佐藤' OR User.name = '中村'
こんな感じ。要は$conditionsのORというキーの中に必要な条件を全部ぶっこめば、CakeがOR検索をしてくれる。ときにはforeach文とかで回すこともあるでしょうが、やり方は同じ。
$array = array(1, 2, 3);
foreach($array as $val) {
$data[] = array('User.id'=> $val);
}
$conditions['OR'] = $data;
//SQL
WHERE User.id = '1' OR User.id = '2' OR User.id = '3'
あるいは
WHERE User.id IN(1,2,3)
みたいな感じにもなるかもしれない
ANDとORが組み合わさった場合
基本的には、上の二つを適当に組み合わせれば問題はない。
上の例にのっとって、年齢が20歳以上で名字が佐藤さんか中村さんのデータを検索してみる。
$conditions['OR'] = array('User.name' => array('佐藤', '中村'));
$conditions[] = array('User.age >=' => '20');
$this->paginate('User', $conditions);
//SQL
WHERE (User.name = '佐藤' OR User.name = '中村') AND User.age >= '20'
とまあ、こんな要領でいいのだけれど、ちょっと面倒なのは、OR同士をANDで結ぶような場合。たとえば、名字が佐藤さんか中村さんで、年齢が20歳以下と60歳以上のデータだけを出力したいなんてことがあったとする。SQLでいうと、以下のような出力結果が欲しい場合。
WHERE (User.name = '佐藤' OR User.name ='中村') AND (User.age <= '20' OR User.age >= '60')
こんなときは、配列の次元をもう一つ増やす。
$conditions[] = array('OR' =>
array('User.name' => '佐藤', '中村'),
array('User.age <=' => '20', 'User.age >=' => '60'),
);
$this->paginate('User', $conditions);
余談だけど、検索条件にHABTMで関連づいているデータを使うの、結構めんどいですな。ソースがどうも奇麗にまとまらないっす……。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。