CakePHPのrecursive=2のデータの取ってきたがよくわからんちん。
CakePHPでfindとかを使うときにrecursiveでアソシエーションするレベルを制御できるっていうのをつい最近知ったんですが、belognsToのテーブルを2階層分取って来たい時でもSQLの発行が3回以上されてる。なんか使い方間違っているのかしら。
えごリブでもいくつか使えそうな部分があると思っているんですが…、どうしたものか。
具体的には下記のような感じのテーブルがあるとします。
user_items(UserItem)
id | item_id | user_id |
---|---|---|
1 | 1 | 1 |
2 | 3 | 1 |
items(Item)
id | name | category_id |
---|---|---|
1 | hoge | 1 |
2 | fuga | 1 |
3 | bar | 2 |
categories(Category)
id | name |
---|---|
1 | book |
2 | game |
user_itemsのアソシエーション
var $belongsTo = array("Item");
itemsのアソシエーション
var $belongsTo = array("Category");
要するに、ユーザーアイテムはアイテムに対して多対1で、アイテムはカテゴリーに対して多対1のような関係です。
で以下のようなfind文を実行する
$result = $this->UserItem->find("all", array( "limit" => 20, "recursive" => 2 ));
そうすると、Itemは当然一発でleft joinして取ってきてくれるんですがCategoryは別SQLを発行して取ってきてる。以下みたいな感じ。
SELECT `UserItem`.`id`, `UserItem`.`user_id`, `UserItem`.`Item_id`, `Item`.`id`, `Item`.`name`, `Item`.`category_id` FROM `user_items` AS `UserItem` LEFT JOIN `items` AS `Item` ON (`UserItem`.`Item_id` = `Item`.`id`) LIMIT 20 SELECT `Item`.`id`, `Item`.`name`, `Item`.`category_id` FROM `items` AS `Item` WHERE `Item`.`id` = 1 SELECT `Category`.`id`, `Category`.`name` FROM `categories` AS `Category` WHERE `Category`.`id` = 1 .....
というわけでしょうがないので現在はrecursivを-1にして、普通にjoinして取ってくるようにしていますがいいのかな。ちなみに以下のようにしてます。
$result = $this->UserItem->find("all", array( "limit" => 20, "recursive" => -1, "joins" => array( array( "table" => "items", "alias" => "Item", "type" => "LEFT", "conditions" => array("Item.id = UserItem.item_id") ), array( "table" => "categories", "alias" => "Category", "type" => "LEFT", "conditions" => array("Category.id = Item.category_id") ) ), "fields" => array("UserItem.* , Itemt.* , Category.*") ));
こうすると、SQLは一回しか発行されないのですっきりするんですが、使い方としてあってるんだろうか。