Cakephp3.9以上?私が現在使用しているCakephp4.1では多対多のリレーションが上手く設定できるとかなり使えます。
たた、上手く設定できないと非常に困難なものになってしまい、SQLでそのままQueryを書くほうがええんちゃうか?というぐらいに困難なものになってしまいます。
Cakephpの書籍もありますが、多対多の紹介は少しだけで、具体的な使い方は書いていません。
検索してもCakephp4のわかりやすいものが無い。。
ので、私が実践的なものをまとめておきますね。
まず、ここでは3つのテーブルを使います。
1,[minurls]テーブル
2,[minurls_tags]テーブル
3,[tags]テーブル
1と3を使おうと思うと、必ず2が必要になります。
データ構造については、他サイトに譲らせてもらいます。
まずはMinurlsTable.php
public function initialize(array $config): void { parent::initialize($config); $this->setTable('minurls'); $this->setDisplayField('id'); $this->setPrimaryKey('id'); ・ ・ ・ $this->belongsToMany('Tags');//ここは大文字小文字をコントローラーと一緒にしないとダメ }
「belongsToMany('Tags')」を入れます。
TagsTable.php
public function initialize(array $config): void { parent::initialize($config); $this->setTable('tags'); $this->setDisplayField('name'); $this->setPrimaryKey('id'); ・ ・ ・ $this->belongsToMany('Minurls'); }
「belongsToMany('Minurls')」を入れます
MinurlsTagsTable.php
public function initialize(array $config): void { parent::initialize($config); $this->setTable('minurls_tags'); $this->setDisplayField('id'); $this->setPrimaryKey('id'); $this->addBehavior('Timestamp'); //これを入れる! $this->belongsTo('Minurls', [ 'foreignKey' => 'minurl_id', ]); $this->belongsTo('Tags', [ 'foreignKey' => 'tag_id', ]); }
MinurlsTagsTable.phpこれは多対多を中間にあるテーブルなので、両方の外部キーを間違えず指定しておく。
そういう下準備をしたら下記のようなことができます。
$condition = ['conditions'=>['user_id'=>$user_id]]; $taglist2 = $this->Minurls->find('all',$condition) ->contain('Tags') ->enableHydration(false) ->toArray(); debug($taglist2);
これはユーザー毎にタグ(tag)を持ったMinurlを出すソースコードです。
ポイントは、containです。ここでTagsを指定するとタグ関連まで引っ張って来てくれます。
なお、user_idで特定のユーザーを指定しています。
次に、必要なものがタグの一覧でしょう。
タグの一覧もユーザーごとに出す必要があるので、このようになります。
$taglist = $this->Tags->find() ->matching('Minurls', function($q) use ($user_id){ return $q->where(['Minurls.user_id'=>$user_id]);}) ->enableHydration(false) ->toArray(); debug($taglist);
ポイントは、matchingです。ここでfunctionを使って、useでそこで使用する変数を指定します。
なお、このmatchingをcontainにしてしまうと、user_idが効かなくなるのでご注意を。