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

Laravel

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

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

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

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

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

【Laravel】中間テーブルを使ってみる (基本編) | Zakkuriブログ
Laravelで多対多のリレーションを扱うにあたり、中間テーブルの使い方をまとめてみた

tableを作る

table概要

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

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

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

  • club_userテーブル
id user_id club_id
1 1 1
2 1 2
3 2 2
4 4 3

説明をすると、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_table

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')->onDelete('cascade')->comment('');
            $table->foreign('club_id')->references('id')->on('clubs')->onDelete('cascade')->comment('');
            $table->timestamps();
    });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('club_user');
    }
}

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名}

app/Models/User.php

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

app/Models/Club.php

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

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

リレーション先の取得

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

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

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

【ダミーデータの作成】laravel8系でseederを使ってダミーデータを作成してみた。
今回はseederを使ってダミーデータを作成してみます。使うのはlaravel8系です。シーダーの作成#シーダ名はアッパーキャメル型で書く。 ex.TestTableSeederphp artisan make:seeder シーダ...

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

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

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

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

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

その他の取得方法

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

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

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

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

まとめ

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

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

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

コメント

タイトルとURLをコピーしました