CakePHP(MySQL)でちょっと変わった検索条件。

久しぶりのCakePHPネタです。30日ブログに機能を追加しました。
http://30daysblog.com/
30日ブログ

数ヶ月ぶりにソースコードを覗けば、もはや自分で書いたものとは思えない世界が広がっていました。
それでも既存コードをコピペしてイジリながらで、思っていたより簡単に機能追加。
フレームワークでMVCが分離されていることで、後から見返してもわかりやすく、機能の追加がしやすいということを実感しました。
●ランダム表示
DBに登録されている「テーマ」をトップページにランダム表示(3件)するようにしました。
$home_theme = $this->Theme->find('all', array(
'limit'=>3,
'order'=>'rand()',
));

‘order’=>’rand()’はCakePHPではなくMySQLの実装(”order by rand()”)です。
ランダムな数値を出して、それをidの検索条件にして・・・など考えていましたが簡単でした。
●カンマ区切りフィールドの検索
DBに登録されている「テーマ」をカテゴリー別に表示するページを追加しました。
http://30daysblog.com/themes/cateview/1
cateviewという、何ともダサいネーミングのアクションです。
各「テーマ」レコードは「カテゴリー」フィールド(category_id)を持っているのですが、テーマが複数カテゴリーに属するように“1,3,5”のようにCSVでcategory_idを保持しています。
本来DB設計としてはやってはいけないことなんだと思いますが、諸々の面倒を考えこのような形をとっています。
このCSVの中から特定のcategory_idを取得する方法についてWhereのLIKE検索を考えました。
SELECT * FROM db WHERE category_id LIKE ‘%$param%’
しかしこれでは、$paramが”1″の場合、”1″以外に”11″や”10″などにもマッチしてしまいます。
まさに同じような課題を人力検索はてなで見つけました。
MySQLでデータの保存方法について質問です。 1つのフィールド内に「1,2,3」と言うようにカンマ区切りのデータを保存する箇所があります。通常、この部分は正規化して別テー.. – 人力検索はてな
なるほど正規表現を使うのかー。
以下CakePHPでの実装。
function cateview($param = null) {
$data = $this->Theme->find('all', array(
'conditions' => array('Theme.category_id REGEXP' => "^$param$|^$param,|,$param$|,$param,"),
));
$this->set("data", $data);
}

CakePHPではfindを使えば柔軟にSQL文を作成できます。
以下、自分でコピペする際の雛型。
$data = $this->Model->find('all', array(
'conditions' => array("Model.id" => $param,"Model.hoge <>" => ""),//条件式。","でand。比較演算子の位置に注意。
'fields' => array('id', 'title'),//取得するフィールド。未指定は全件。
'recursive' => 0,//アソシエーションの取得数
'order' => 'Model.created desc',//取得順序
'limit' => 100,//取得件数
));

DB設計をいじらない表面上の処理であれば色々と簡単に実装できそうです。

コメント

  1. 匿名 より:

    カンマ区切りでしたら
    「FIND_IN_SET」もアリなのでは?

  2. umakoya より:

    MySQLにはそんな便利な関数があったとは・・・。
    すみません不勉強でして。
    まさに↓ですね・・・。
    MySQL DB の単一カラムに入っている複数データから特定データをマッチングする
    http://idea-tech.sakura.ne.jp/blog/2007/10/mysql_db_1.php

タイトルとURLをコピーしました