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が効かなくなるのでご注意を。