containを使え
あちこちのサイトを見ると、contain を使った方法がたくさん書いてありますね。
たとえば、products テーブルに取引先のIDである partner_id が含まれているとき
$product_id で示されるレコードを取得するには、次のように書きます。
// コントローラの initialize() で
$this->loadModel('Products');
// レコードの取り込み処理で
$record = $this->Products->get($product_id, ['contain' => ['Partners']]);
cakePHP を書きなれている人なら、同じみでしょう。
QueryBuilder を使った find() などでもアソシエーションとともに読み込みできますね。
$record = $this->Products->find()
contain(['Partners'])
->first();
どんだけ書くねん!
『こう書いておけば動く』から、なんでしょうか・・・
たぶん、世界中の人が、さまざまなプロダクトのテーブル参照を『とっても便利な』QueryBuilder を使って読み込んでいるのでしょうね。
おおきなプロダクトになってくると、それぞれのテーブルごとにレコード参照のコントローラ.phpファイルが増えて、手に負えなくなってしまいますねぇ
簡単にしちゃいましょう
レコードが _id で示されるインデックス指定のフィールドを持っているとき、contain でアソシエーションを『含めずに』読み込む、なんてことは逆に少ないはずです。
少なくとも、私の担当するプロダクトではレコード読込でアソシエーション不要、なんてことは皆無に近いですね。
そこで、こんなコードを共通コンポーネントに書き加えました。
ようするに、belongsTo, belongsToMany のアソシエーション定義されているテーブルなら、そいつをまとめて読み込んでくれよ、というコードです。
/**
* 指定テーブルのアソシエーション(BelongsTo/BelongsToMany)を含めて
* レコードを取得する
*/
function LoadRecordWithBelongs($table, $id)
{
$record = false;
$contains = [];
$associations = $table->associations();
$items = $associations->getByType(['BelongsTo', 'BelongsToMany']);
foreach($items as $item)
{
$name = $item->getName();
$contains[] = $name;
}
$record = $table->get($id, ['contain' => $contains]);
return $record;
}
まとめ
共通化することで、たくさんのソースを削除することができるようになりますが。
それは、これからやり始めようとしてるところです・・・w
めでたしめでたし。