プログラミング

Cakephp4で多対多のbelongsToManyリレーションでタグ機能

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

-プログラミング
-

© 2024 青い空とコーヒーと