【Laravel8】多対多のリレーションを持つモデルを使ってリレーション先を取得する方法

今回は多対多のリレーションテーブルを作って、リレーション先のデータを取得するようにしてみます!

objectで取得できるものをarray(配列)でも取得してみようと思います!

中間テーブルの命名規則とかにもちょっとはまってしまった。。。

それでは行ってみよーー (oノ´3`)ノ ピューーン!!

参考
https://readouble.com/laravel/8.x/ja/eloquent-relationships.html

tableを作る

table概要

一旦こんな感じのテーブルを作ります↓

  • usersテーブル
idnameage
1山田17
2田中18
3中本17
4井出16
  • clubsテーブル
idname
1野球
2サッカー
3柔道
4バスケ

そして、上記のテーブルをつなぐ中間テーブルを作成します。

  • club_userテーブル
iduser_idclub_id
111
212
322
443

説明をすると、userは複数のclubに所属できるようになっています。
clubは複数のuserを所属させることができます。

これが多対多のリレーションになっています。

ほい、ではここからテーブルを作っていきましょう

tableの作成

table作成コマンド

※中間テーブルを作成するときの命名規則にも注意してください。

//table作成時table名は複数系にする必要がある。 例) create_user_tableはダメ×
php artisan make:migration create_users_table
php artisan make:migration create_clubs_table

//中間テーブルは対象のテーブルを単数形にして作成。 今回の場合はclubsテーブルとusersテーブルを合わせてclub_user
//tableの順番はアルファベット順 clubのc userのu で考える
php artisan make:migration create_club_user_tableCode language: JavaScript (javascript)

usersテーブルとclubsテーブルの作り方はここではスキップ

database/migrations/yyyy_mm_dd_xxxxxx_create_club_user_table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateClubUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('club_user', function (Blueprint $table) {
            $table->id();

            $table->unsignedBigInteger('user_id')->comment('ユーザーID');
            $table->unsignedBigInteger('club_id')->comment('クラブID');

            //外部キー
            $table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade')->comment('');
            $table->foreign('club_id')->references('id')->on('clubs')->onUpdate('cascade')->onDelete('cascade')->comment('');
            $table->timestamps();
    });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('club_user');
    }
}
Code language: HTML, XML (xml)

Modelにリレーションの設定

多対多のリレーションしますよーっていうのをModelに書きます。

使うのはBelongsToManyです。

↓参考
https://readouble.com/laravel/8.x/ja/eloquent-relationships.html#many-to-many

もしModelが作成されていなかったら以下コマンド

//model名はアッパーキャメル記法で書く ex. User, TestUser
php artisan make:model {Model名}Code language: JavaScript (javascript)

app/Models/User.php

//追加↓
public function clubs()
{
    return $this->belongsToMany(Club::class);
}Code language: PHP (php)

app/Models/Club.php

//追加↓
public function users()
{
    return $this->belongsToMany(User::class);
}Code language: PHP (php)

はい!これで準備は完了!

リレーション先の取得

とりあえずリレーション先を取得しようと思いますが、データが入ってない…

今回は面倒なのでとりあえずseeder使ってダミーデータ入れることにしまス。

seederの使い方は以下からどうぞ

https://yama-weblog.com/create-dummy-data-using-seeder-in-laravel8/

ほい、そしたら取得していきましょう。

データは最初に確認したtableのデータが入っているとしましょう。

そして以下のようにして対象ユーザが所属するクラブを取得してみました。

ほかにも取得方法はいろいろあるので試してみましょう!

//Requestではuserのidを投げている。
//pluck('name')= clubsテーブルのnameカラムを指定して取得。
//toArray() = オブジェクトとして帰ってくるので配列にして返すようにする。
$clubs = User::find($request->id)->clubs()->pluck('name')->toArray();
return $clubs;Code language: PHP (php)

その他の取得方法

すべてのリレーションはクエリビルダとしても機能するため、rolesメソッドを呼び出し、クエリに条件をチェーンによりつなげることで、リレーションのクエリへさらに制約を追加できます。

$roles = User::find(1)->roles()->orderBy(‘name’)->get();

公式より https://readouble.com/laravel/8.x/ja/eloquent-relationships.html#many-to-many

はい、こんな感じでいろいろやり方はありますね~

まとめ

今回少し時間がかかったところは、

  • 多対多の中間テーブルの命名規則を無視した書き方をしていてエラーで困っていた。
  • objectでは取得できたけど、配列でデータを取得方法につまった。

以上2点にすこし時間がかかりました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA