Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

cakephp1.2で明示的にJOINさせるやり方

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トヾヽ_/ィ"\      `ー'´     /

という気分ではあるw Modelを追いかけるのはあとでいいかみたいなw

階層が違うテーブルでJOINをされたい場合の参考になれば。