データベースのリレーションシップ(多対多)

多対多の関係性

多対多の関係性では、これまでとは少し違うことが必要になります。今までは、外部キーに関連するデータのidを設定していました。1対1や1対多では、登録すべきキーが一つだったため問題ありませんが、多対多では問題が発生します。なぜなら、必要な外部キーが複数あり、データベースのカラムは一つのカラムにつき一つの値しか保存できないため、今までの方法は利用できません。そこで、中間テーブルを用いてこの問題を解決します。

中間テーブル

中間テーブルとは、多対多のリレーションシップを表現するために使用される特別なテーブルです。それぞれのテーブルの主キーを組み合わせたデータを保存します。例えば以下のようなテーブルが考えられます。

user_idcourse_id
11
12
21
22

このテーブルでは、usersテーブルとcoursesテーブルのidの関係性を示しています。ユーザーを講座を受けるユーザー、コースを講座と考えると、ユーザー1はコース1とコース2を受けており、ユーザー2もコース1とコース2を受けています。コース側から見ると、コース1コース2ともに、ユーザー1とユーザー2が受講者であることがわかります。

このように中間テーブルを使用することで多対多の関係性を表現することができます。

多対多の関係性の設定方法

今回は多対多の関係性を設定します。ここでは、UserモデルとCourseモデルを使用し、ユーザーが複数のコースを受講し、コースも複数の受講者がいることの関係性を設定します。Courseモデルは以下の通りです。

カラム名内容
titleコースのタイトル

マイグレーションファイルは簡単なものになるため、詳しいことは割愛します。

中間テーブルの作成

中間テーブルを作成します。中間テーブルの名前は、「テーブル1(単数形)_テーブル2(単数形)_table」であり、テーブル1とテーブル2はアルファベット順になります。usersテーブルとcourseテーブルの中間テーブルの名前は、「course_user_table」となります。以下のコマンドでマイグレーションファイルを作成します。マイグレーションファイルは以下の通りです。

        Schema::create('course_user', function (Blueprint $table) {
            $table->id();
            $table->foreignId("user_id")->constrained();
            $table->foreignId("course_id")->constrained();
            $table->timestamps();
        });

usersテーブルとcoursesテーブルのidを紐づけるだけのマイグレーションファイルとなります。

モデルに関連性を記述

次に、モデルに関係性を記述します。Userモデル、Courseモデルに以下のようにメソッドを追加します。

Userモデル

    public function courses() {
        return $this->belongsToMany(Course::class);
    }

Coiurseモデル

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

belongsToManyメソッドは多対多のリレーションシップを定義するメソッドです。

関係性のテスト

tinkerを使用して関係性をテストします。以下のコードでダミーデータを生成し各データの関係性を設定します。

use App\Models\User;
use App\Models\Course;

#ダミーユーザー1、2
$user1 = new User();
$user1->name = "test1";
$user1->email = "test1@example.com";
$user1->password = Hash::make("password");
$user1->is_admin = false;
$user1->save();

$user2 = new User();
$user2->name = "test2";
$user2->email = "test2@example.com";
$user2->password = Hash::make("password");
$user2->is_admin = false;
$user2->save();

#ダミーコース1、2
$course1 = new Course();
$course1->title = "test course 1";
$course1->save();

$course2 = new Course();
$course2->title = "test course 2";
$course2->save();

#ユーザーとコースの紐づけ
$user1->courses()->attach([1,2]);
$user2->courses()->attach([1,2]);

Userモデルのcoursesメソッドにあるattachメソッドでデータの紐づけを行います。紐づけしたいコースのidをattachメソッドに引き渡します。

次に、データベースの関係性が設定できているかどうか確認します。以下のコマンドで、user1、user2から紐づけたコースのデータが、course1、course2から紐づけたユーザーのデータが取得できるか確認します。また、紐づけたデータすべてが取得できるか確認します。

$user1->courses;
$user2->courses;
$course1->users;
$course2->users;

上記のコマンドで、コース、ユーザーの情報が取得できれば成功です。

ここまでで、データベースのリレーションシップについて解説してきました。リレーションシップを使用することでデータベースのさらなる利用ができるようになると思います。

コメントを残す

CAPTCHA