

cakephp3で下記２つのテーブルのアソシエーションを定義しようと思っています。

テーブル１：usersテーブル  
ユーザーの特性を定義するテーブル。

テーブル２：languagesテーブル  
プログラミング言語を定義するマスターテーブル。

usersテーブルには、main_languageとsub_languageというカラムがあって、languagesテーブルに定義してあるidを参照する形になっています。

この場合、cakephp3ではどのようにアソシエーションの定義をすれば良いでしょうか？よろしくおねがいいたします。


CC BY-SA 3.0
2018-04-10T11:35:47.830
43130
2018-04-12T02:08:31.227
20807
question
cakephp
cakephp3のアソシエーション


`users` テーブルに対応するTableクラス `UsersTable`, `languages` テーブルに対応するTableクラス
`LanguagesTable` は既に定義済みとします。

質問のテーブル設計の場合、`users` → `languages` の関係はbelongsToになります。

[belongsTo アソシエーション | アソシエーション - モデル同士を繋ぐ -
3.5](https://book.cakephp.org/3.0/ja/orm/associations.html#belongsto)

`UsersTable`の`initialize()`メソッドに次のようにしてリレーションを定義します。

[code]

    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',
            ]);
        }
    }
    
[/code]

上記の指定をすることで、以下のようにして取得できます。

[code]

    $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;
    
[/code]

なお、CakePHPの規約に沿うのであれば、usersテーブルの外部キーとなる `main_language`, `sub_language` は、
`main_language_id`, `sub_language_id` とすべきで、プロパティ名に `main_language`,
`sub_language` を使用した方が自然です。


CC BY-SA 3.0
2018-04-12T02:08:31.227
43174
2018-04-12T02:08:31.227
2668
43130
answer