CakePHPで3つ以上の複数テーブルを結合

Posted by joeartsea on 2009-03-13

CakePHPで3つ以上の複数テーブルを結合します。SQLならば基本的な結合で難なくこなせますが、CakePHPのアソシエーションはhasOne, hasMany, belongsTo, hasAndBelongsToManyだけなので一見無理そうに見えます。アソシエーションについて詳しくは関連-モデルを結びつけるを参照してください。

このhasOne, hasMany, belongsTo, hasAndBelongsToManyを覚えれば、業務において頻繁に発生する「bテーブルのc_idをキーとしてcテーブルのnameを取得する」という結合要件は難なくクリアできます。しかし「aテーブルのb_idをキーとしてcテーブルのnameを取得する」にはどうしたら良いのでしょうか?

CakePHPのモデルはそれぞれがひとつで完結しますから「bテーブルは常にcテーブルと結合されるもの」として考えれば物事は単純になります。したがってb-cの関係はa-bの関係からは関知しないということです。ならばb-cを関連付けたのと同じようにa-bを関連付ければいいだけ…のはずなんですが単純にa-bを関連付けてもb-cの結合結果を持ってくることはありませんでした。

解決方法は実に簡単でコントローラでモデルを使う際に以下のように書くだけです。

1
2
$this->a->recursive = 2;
$this->a->findAll();

要は階層数を指定することで結合先に更に結合先があればそれを関連させた結果を取得すると言うことです。recursiveはモデルのメンバなので設定後は常に2階層になります。次にモデルを使う時は1階層じゃないとまずいというような場合は、次のモデルを使う際に同じように$this->a->recursive = 1;として上書きすれば問題ありません。