cakephpのversion:1.2.2.8120
今回JOINしたかったのは、A、B、Cという3つのテーブル。
JOINの条件としては、「A.id = B.A_id」と「B.id=C.B_id」というもの。A→BがhasManyでB→CがBelongToと言えば分かりやすいと思う。
こーゆー時はアソシエーションで頑張っても無理っぽいので、明示的にJOINを指定するしかない。アソシエーションは1:N:1とか、そういうのまで頑張ってはくれない。
もちろん、既に先駆者はいらっしゃる。
が、いちいちフックメソッドをModelに定義したり、フレームワークのコードを改変するのはちょっとイヤだった。パラメータを渡してあとはよきにはからえ、がしたかった。
次に見つけたのがこちら。
おおお!これだあぁぁ!
というわけで、コレにインスパイアされて、こんなコードを書いて解決した。
<?php $options['conditions']=array("A.id"=>$id); $options['fields']=array("A.id","B.id","B.num","B.C_id","C.name","C.code"); //1. なぜか二次元配列にすると素直にJoinされた。$option['joins']ではダメ。 //cake/libs/model/model.php#findを追いかけて確認したい。 $options['joins'][]= array( "type" => 'LEFT',//join type "alias" => 'B',//alias "table" => 'B',//tablename "conditions" => 'A.id = B.A_id' // joinのon句にあたる ); $options['joins'][1]= array( "type" => 'LEFT', "alias" => 'C', "table" => 'C', "conditions" => 'B.C_id = C.id' ); //2.第一引数にallと入れるとfindAll的に使える。 $result = $this->find("all",$options);
tablenameはcakeの規約では複数形なので、そこだけ注意してね。
$Model->find()の第1引数にallと入れても使えるよっていう風に、cakeのソース自身のコメントに書いてある。
<?php /** * Returns a result set array. * * Also used to perform new-notation finds, where the first argument is type of find operation to perform * (all / first / count / neighbors / list / threaded ), * second parameter options for finding ( indexed array, including: 'conditions', 'limit', * 'recursive', 'page', 'fields', 'offset', 'order') * * Eg: find('all', array( * 'conditions' => array('name' => 'Thomas Anderson'), * 'fields' => array('name', 'email'), * 'order' => 'field3 DESC', * 'recursive' => 2, * 'group' => 'type')); * (以下略
これを解決するのに1.2Hぐらいかかったので、正直なところ、
/)
///)
/,.=゙''"/
/ i f ,.r='"-‐'つ____ こまけぇこたぁいいんだよ!!
/ / _,.-‐'~/⌒ ⌒\
/ ,i ,二ニ⊃( ●). (●)\
/ ノ il゙フ::::::⌒(__人__)⌒::::: \
,イ「ト、 ,!,!| |r┬-| |
/ iトヾヽ_/ィ"\ `ー'´ /
///)
/,.=゙''"/
/ i f ,.r='"-‐'つ____ こまけぇこたぁいいんだよ!!
/ / _,.-‐'~/⌒ ⌒\
/ ,i ,二ニ⊃( ●). (●)\
/ ノ il゙フ::::::⌒(__人__)⌒::::: \
,イ「ト、 ,!,!| |r┬-| |
/ iトヾヽ_/ィ"\ `ー'´ /
という気分ではあるw Modelを追いかけるのはあとでいいかみたいなw
階層が違うテーブルでJOINをされたい場合の参考になれば。