• WEB

CakePHPのfindで複雑な条件

  • まーしー
    まーしー システムちーむ
  • このエントリーをはてなブックマークに追加
CakePHPのfindで複雑な条件

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のところで()が一つ多い気がするけれど、ほしい検索結果が取得できました。

とても複雑な検索条件も、複数の配列をネストすることで実現可能です。
とありましたが、本当のようです。

参考

以下参考にしたページを載せます。


CakePHPのfindで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を使わず配列に入れています。

このエントリーをはてなブックマークに追加

まーしーが最近書いた記事

WRITERS POSTS もっと見る

他にもこんな記事が読まれています!

  • WEB
  • マーケティング
  • サーバー・ネットワーク
  • ライフスタイル
  • お知らせ