bindModelを複数するときはrecursiveが大事
複数のbindModelをするときはrecursiveが大事
久々にCakephpの話題なのですが、複数bindModelしたい時はrecursiveが非常に大事というお話。
例:4つのテーブルを連携する
今回私は4つのテーブル(Model) を使いました。これだけ多数のModelを使うと、4つ全てが関連付け(foreignKey)されあっていることはないですわね。言い換えると、あるModelの中で別のModelを扱うということ。
例だと、最終行を見てもらった通りGroupShopが一番の親になるわけです。
各Modelの関係性
この関係性だと、GroupShop Prefectureこの2つが関係しあってないので、GroupShopに対してbindModelできません。どう頑張っても。
そこで、唯一関係しあっているShopモデルと先にbindModelで別にbindしておく必要があります。
ShopとPrefecture | 関連 |
---|---|
ShopとGroupShopとGroup | 関連 |
GroupShopとPrefecture | 関連していない |
下記はコントローラーの内容です。
$this->Shop->bindModel(
array(
'belongsTo'=>array(
'Prefecture'=>array(
'className'=>'Prefecture',
'conditions'=>'',
'order'=>'',
'foreignKey'=>'prefecture_id'
)
)
));
$this->GroupShop->bindModel(
array(
'belongsTo'=>array(
'Group'=>array(
'className'=>'Group',
'conditions'=>'',
'order'=>'',
'foreignKey'=>'group_id',
),
'Shop'=>array(
'className'=>'Shop',
'conditions'=>'',
'order'=>'',
'foreignKey'=>'Shop_id',
)
)
));
$con = array(
'conditions'=>array('group_id'=>$id) ); $groups = $this->GroupShop->find('all',$con);
上記の書き方ではあるものが抜けているので 最初にbindeModelしたPrefectureのデータまで拾うことは出来ません。
なお、Modelで結合させても結果は同じです。忘れがちなあるものが無いのです。
bindModelはデフォルトでは第一階層までしか見ない
Cakephpは特に指定しなければ結合してあるModelの第一階層、つまり自分が直接結合しているModelしか読みに行かず、孫(ここではShopと関連付けされているPrefecture)
を一切見てくれません。そこで、さらに下の階層まで読みにいかせる場合はrecursiveを指定してあげる必要があります。
recursiveとは深度のことです。
findするModelにrecursiveを指定する
今回、自分は直接結合していない孫のModelの内容まで見る場合は’recursive’ => 2にしてあげれば 孫まで読みに行くことが出来るようです。
$con = array(
'conditions'=>array('group_id'=>$id),
'recursive' => 2
); $groups = $this->GroupShop->find('all',$con);
単純なことのようで、知らないってことってあるんですね。
Cakephpの参考書にもrecursiveについては載っているのですが、深度ですよ~との説明しかなかったので、
今まで全く気にしていなかったのですが、今回のように自分が直接bindしていないModelを読みにいく場合は使えそうです。
3.7.8.6 recursive
なお、Cakephpのマニュアルにあるとおり、必要以上に設定すると処理が重たくなるので必要最低限にしましょうとのこと。
このまま見過ごしていたら、サブクエリで全部やるところでした。ヤレヤレ。