多対多の関係とは
テーブルのデータが互いに他方のテーブルの多数と結びついている関係。
例えば
SNSの「いいね」のように多数のユーザと多数のツイートを結びつけるような機能の場合。
ユーザは複数のツイートに「いいね」できる。
ツイートは複数のユーザから「いいね」を受けられる。
2つのテーブルだけではこのような多対多の関係性を表すことはできない。
中間テーブル
両テーブルの関係性を羅列した中間テーブルを設け、中間テーブルと2つのテーブルそれぞれで一対多の関係を結びつけることにより、中間テーブルを介した多対多の関係とする。

usersテーブル、tweetsテーブルそれぞれがfavoritesテーブル(中間テーブル)に一対多で結びつく。
先ほどの関係は下のように表せる。
user_id | tweet_id |
---|---|
1 | 1 |
1 | 2 |
2 | 2 |
2 | 3 |
ユーザテーブルとツイートテーブルはfavoritesテーブルを介して互いのidを知ることができるようになる。
マイグレーションで外部キーの設定する
favoritesテーブル(中間テーブル)ではuserとtweetのidを参照するためそれらの外部キーを設定する。
public function up()
{
Schema::create('favorites', function (Blueprint $table) {
$table->unsignedInteger('user_id');
$table->unsignedInteger('tweet_id');
$table->primary(['user_id','tweet_id']);
// 外部キー制約
$table->foreign('user_id')->references('id')->on('courses')->onDelete('cascade');
$table->foreign('tweet_id')->references('id')->on('students')->onDelete('cascade');
});
}
モデルでリレーションを定義する
リレーションメソッドをbelongsToMany()で定義。メソッド名は複数形となる。
class User extend Model
{
public function tweets()
{
return $this->belongsToMany(Tweet::class);
}
}
class User extend Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
}
これで関係の定義はできたと思います。
多対多の紐づけの操作(中間テーブルへのinsert、deleteの操作)、attach(),detach()については違う記事でまとめています。
多対多のリレーション(紐づけ操作について)