読者です 読者をやめる 読者になる 読者になる

【CakePHP】関連先テーブルの先のテーブルデータを取得する

cakeのrecursive関連では毎回苦しめられるので、今回少しわかったことをメモ。
やりたかったことは題の通り、関連先のその先のテーブルデータ取得。
せっかくなのでrecursiveについても軽くまとめ。

※追記※
結局あまり利便性が良くないので、joinsオプションを使用して結合は自力でやりました。

環境

CakePHP 2.4
PHP 5.3

テーブル仮定

Theme - Post - User

上記のように3つのテーブルにリレーションが張られている場合に、Themeモデルで行うfindでUserのデータを取得したい。
リレーションは表した通り、ThemeとPostおよびPostとUserの間で張られているものとする。

関連先のみ

関連先のテーブルデータだけを取得する場合には、
recursive = 0を設定すれば、リレーションがhasOneおよびbelongsToのデータを取得可能であり、
recursive = 1を設定すれば、リレーションがhasManyのデータを取得可能である。

関連先のその先

hasOneにしろbelongsToにしろhasManyにしろ、関連先のその先のデータを取得するにはrecursiveを2に設定する。

このとき、PostがUser以外のリレーションを複数所持している場合、
Like - Post - Comment (例えばこのような感じ)
そのまま取得してしまうと、クエリ量がやたら増大してしまう。

なので、取得したい関連先の先のテーブルが予め決まっている場合は、関連先で取得するフィールドに制限を設ける。

例えば

'recursive' => 2,
'fields' => array('Theme.*', 'Post.*')

と全てのフィールドを取得すると、User, Like, Commentの各々全てを取得するクエリを発行してしまう。

取得するテーブルを制限するためには

'recursive' => 2,
'fields' => array('Theme.*', 'Post.user_id')

という感じで、取得したい関連先の先とリレーションしている外部キーをfieldsに指定すればOK。



以上ざっくりまとめ。

詳細は参考先を見れば良いと思われる。

正直簡単な事に関してのORマッパーの楽さは群を抜いてると思うけど、ちょっと込み入ったクエリを発行したいときの行き詰まり感が半端ない。
あまり簡略化するのも良し悪しという感じ。


参考
recursiveの正しい理解CakePHP - CPA-LABテクニカル
モデルの属性 — CakePHP Cookbook 2.x ドキュメント