bindModelを複数するときはrecursiveが大事 ITかあさん

ITかあさん

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のマニュアルにあるとおり、必要以上に設定すると処理が重たくなるので必要最低限にしましょうとのこと。

このまま見過ごしていたら、サブクエリで全部やるところでした。ヤレヤレ。

初夏のJavaScript祭 in サーキュレーションビル ForPro