CakePHPでfindの検索条件conditionsを使う時
最近検索のシステムを扱ったところ、CakePHPのfindの検索条件を指定するところが難しく感じたのでまとめてみます。
公式クックブック
まずは公式CookBookのデータ取得を読んで勉強します。
クックブックの
複雑な検索条件
というところです。
CakePHPはSQLのWHERE句にセットされる検索条件を配列で表現するようになっています。
conditionsに検索条件を連想配列で指定するのですが、ここに関する話です。
・A AND B
検索条件に新しい条件を追加したければ、キーと値のペアを配列に追加するだけです。
array (
"Post.title" => array("First post", "Second post", "Third post"),
"Post.created >" => date('Y-m-d', strtotime("-2 weeks"))
)
ちなみに、titleのarray()のところはIN句(このリストの中のいずれかの値に一致するかどうか。ORで置き換えられる)になります。
・A OR B
array("OR" => array(
"Post.title" => array("First post", "Second post", "Third post"),
"Post.created >" => date('Y-m-d', strtotime("-2 weeks"))
))
連想配列のキーをORにします。
ちょっと複雑に
・A AND ( B OR C)
array(
"Author.name" => "Bob",
"OR" => array(
"Post.title LIKE" => "%magic%",
"Post.created >" => date('Y-m-d', strtotime("-2 weeks"))
)
)
とても複雑な検索条件も、複数の配列をネストすることで実現可能です。
・(A OR B)AND (C OR NOT(D))
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'))
)
)
)
)
)
連想配列のキーで’OR’が2つ使えないから、ANDを挟んでいます(ムズイ)。
上のサンプルは次のようなSQLを生成します。(WHERE句のみ)
WHERE
(
(`Company`.`name` = 'Future Holdings')
OR
(`Company`.`name` = 'Steel Mega Works')
)
AND
(
(`Company`.`status` = 'active')
OR
(NOT (`Company`.`status` IN ('inactive', 'suspended')))
)
今回自分が作成したものと結果
(
(条件),
(条件)
[OR] => Array
(
(条件),
(条件)
)
[NOT] => Array
(
(条件)
)
[AND] => Array
(
[OR] => Array
(
[0] => Array
(
[status] => 1
[flag] => 0
)
[1] => Array
(
[status] => 1
[flag] => 1
)
)
)
)
↓
WHERE `Entry`.`
delete_flag` = '0'
AND (条件)
AND ((条件)
OR (条件))
AND NOT (条件)
AND (
(
(
(status = 1) AND (flag = 0)
)
)
OR (
(
(status = 1) AND (flag = 1)
)
)
)
ORのところで()が一つ多い気がするけれど、ほしい検索結果が取得できました。
とても複雑な検索条件も、複数の配列をネストすることで実現可能です。
とありましたが、本当のようです。
参考
以下参考にしたページを載せます。
$conditions = array('name IS NOT NULL',
array("OR"=>array('company_id IS NULL', 'company_id'=>1)),
array("OR"=>array('post_id IS NULL', 'post_id'=>1))
);
こうすると、前のORが上書きされなくなります。
今回自分が作成したものではANDを挟んでいましたが、ANDを使わず配列に入れています。