2015 年 9 月 23 日 水曜日
本日のピンポイント・コードリーディングはCheeseCake2のタグ検索。
HABTMで関連付けられているモデルでのタグ検索(一方のテーブルのカラムをキーにしてもう一方のテーブルのレコードを抽出する)方法ではまったので、CheeseCakeではどのようにタグ検索を実現しているか調べてみた。
PhotoモデルとTagモデルはhasAndBelongsToMany(HABTM)で関連付けられています。
タグ検索は、2つのモデル間を結びつけるphotos_tagsを介して行いますが、CakePHP hasAndBelongsToManyでページング(SQL LIMIT)とかを設定するにもあるとおり、hasMany関連での検索と同じ方法ではデータを抽出することができません。
× $data = $this->Photo->findAll('Tag.id'=>$id);
↑ PhotoはTagをLEFT JOINしていないので、Tag.idでの条件指定はできない
それでは、CheeseCakeではどのようにタグ検索を行っているのでしょうか。
CheeseCakeでは、以下のようにquery文を発行してデータを抽出しています。
return $this->query('SELECT '. $fields.',
COUNT(DISTINCT t.tag) AS uniques
FROM '. $prefix.'photos Photo,' .
$prefix.'photos_tags pt,' .
$prefix.'tags t
WHERE Photo.id = pt.photo_id
AND t.id = pt.tag_id
AND t.tag IN ("'.implode('", "', $tags).'")'.$conditions .
'GROUP BY pt.photo_id HAVING
uniques = ' . count($tags) .
'ORDER BY Photo.created DESC
LIMIT '.$offset.', '.$limit
);
上記のコードがPhotoモデルのpaginateアクションに記述されています。queryを発行する以外にも方法はありますが、他の方法と比べて自由度は高い。
Cakeのメソッドに頼るよりも、自分でクエリを作成したほうが容易く処理を実装できることもある、ということは覚えておきたい。
このエントリーのトラックバックURL:
http://www.bmoo.net/archives/2009/01/142059.html/trackback