findで複数のORを使う場合はarrayで囲む
CakePHPでfind使うとき
SELECT * FROM t WHERE "id" = '1' AND (("status" = '1') OR ("flg" = '1'));
というSQLが書きたければ
find('find', array( 'conditions' => array( 'id' => 1, 'OR' => array( 'status' => 1, 'flg' => 1, ), ), ));
みたいな感じで書くと思います。
で、今回2個のORが使いたいなと思ったんですが、
普通に書いてしまうと
find('find', array( 'conditions' => array( 'id' => 1, 'OR' => array( 'status' => 1, 'flg' => 1, ), 'OR' => array( 'status' => 2, 'flg' => 2, ), ), ));
となってしまうため前のORが後から書いたORに上書きされてしまうなと。
ということでCookbookを調べてみたらちゃんと書いてありました。
array( 'OR' => array( array('Company.name' => 'Future Holdings'), array('Company.city' => 'CA') ), 'AND' => array( array( 'OR'=>array( array('Company.status' => 'active'), 'NOT'=>array( array('Company.status'=> array('inactive', 'suspended')) ) ) ) ) );
なるほどなるほど。ANDでくくればいいのね。上手くいきました。
でも、「今回は2個だったので良いけど3個以上だったらどうするんだろう?」と疑問に。
さっきのORと同じ問題でANDをもう一つ書くわけにはいかない。
と考えてた時に「そういえば同じフィールドの条件を渡したいときにarrayで配列にしてたな」と思い出し、
もう一度Cookbookを参照。
array( 'OR' => array( array('Post.title LIKE' => '%one%'), array('Post.title LIKE' => '%two%') ) );
ありました。ありました。連想配列にせず、普通の配列でも渡せるようです。
ってことで、以下のようにすればORを複数にして渡せました。
find('find', array( 'conditions' => array( 'id' => 1, array('OR' => array( 'status' => 1, 'flg' => 1, )), array('OR' => array( 'status' => 2, 'flg' => 2, )), array('OR' => array( 'status' => 3, 'flg' => 3, )), ), ));
上のfindは下のようなSQLになります。
SELECT * FROM t WHERE "id" = '1' AND (("status" = '1') OR ("flg" = '1')) AND (("status" = '2') OR ("flg" = '2')) AND (("status" = '3') OR ("flg" = '3')) LIMIT 1