質問: cakephp3で下記2つのテーブルのアソシエーションを定義しようと思っています。 テーブル1:usersテーブル ユーザーの特性を定義するテーブル。 テーブル2:languagesテーブル プログラミング言語を定義するマスターテーブル。 usersテーブルには、main_languageとsub_languageというカラムがあって、languagesテーブルに定義してあるidを参照する形になっています。 この場合、cakephp3ではどのようにアソシエーションの定義をすれば良いでしょうか?よろしくおねがいいたします。
回答: `users` テーブルに対応するTableクラス `UsersTable`, `languages` テーブルに対応するTableクラス `LanguagesTable` は既に定義済みとします。 質問のテーブル設計の場合、`users` → `languages` の関係はbelongsToになります。 belongsTo アソシエーション | アソシエーション - モデル同士を繋ぐ - 3.5 `UsersTable`の`initialize()`メソッドに次のようにしてリレーションを定義します。 ``` class UsersTable extends Table { public function initialize(array $config) { // ... $this->belongsTo('MainLanguage', [ // リレーション名(任意の名前を指定) 'className' => 'Languages', // 相手先のテーブルクラス名 'foreignKey' => 'main_language', // 当該のテーブル上の外部キーの名前 'propertyName' => 'main_language_obj', // エンティティ化したときに紐付けるプロパティ名(任意の名前を指定) ]); $this->belongsTo('SubLanguage', [ 'className' => 'Languages', 'foreignKey' => 'sub_language', 'propertyName' => 'sub_language_obj', ]); } } ``` 上記の指定をすることで、以下のようにして取得できます。 ``` $user = $this->Users->find('all') ->contain(['MainLanguage', 'SubLanguage']) // contain句を忘れずに ->first(); // main_language の languages.name を参照 $user->main_language_obj->name; // sub_language の languages.name を参照 $user->sub_language_obj->name; ``` なお、CakePHPの規約に沿うのであれば、usersテーブルの外部キーとなる `main_language`, `sub_language` は、 `main_language_id`, `sub_language_id` とすべきで、プロパティ名に `main_language`, `sub_language` を使用した方が自然です。