はじめに
多対多のリレーションを持つテーブルの Eloquent に触れたので整理をしておこうと思います。
多対多の前提設定
今回はユーザーとロールの例で話をすると、まずは以下のテーブルが存在していることになります。
- users
column name | column type |
---|---|
id | integer |
name | string |
- roles
column name | column type |
---|---|
id | integer |
name | string |
- role_users
column name | column type |
---|---|
role_id | integer |
user_id | integer |
上記のテーブルに対して、User クラスと Role クラスにはそれぞれ以下の様に多対多リレーションメソッドを定義します。
- User 側
public function roles()
{
return $this->belongsToMany(Role::class);
}
- Role 側
public function users()
{
return $this->belongsToMany(User::class);
}
ちなみに、belongsToMany()
は第4引数までを用いることで、中間テーブルや中間テーブルで使用するカラム名の指定が可能です。
- 形式
belongsToMany(相手のクラス, 中間テーブル名, 自身のIDを指すカラム名, 相手のIDを指すカラム名)
- 実例(User 側)
public function roles()
{
return $this->belongsToMany(Role::class, 'role_users', 'user_id', 'role_id');
}
多対多リレーションの更新
多対多のリレーションを更新する際は、
$user->roles()->更新用メソッド(相手のIDの配列);
という形式で更新を行うことが多いですが、この更新用メソッドは大きく分けて以下の3つが存在します。
・attach():関連付け
・detach():関連解除
・sync():同期
attach()/detach()
attach
はリレーションの追加のみ、detach
はリレーションの解除のみを行うメソッドです。
用途としては、以下の様にそれぞれに対して追加 or 解除を実行する場合に向いています。
権限名 | 操作 |
---|---|
admin | [ 解除 ] |
manager | [ 解除 ] |
normal | [ 追加 ] |
ちなみに、detach
に関しては引数なしでの実行も可能であり、引数なしで実行すると実行元のレコードが持つリレーションを全て解除します。
sync()
sync
は引数で渡された ID 配列に指定されている ID のみとリレーションが結ばれるように追加及び解除を行います。
引数なしのdetach
の後にattach
を行うことで得られるリレーションと同じリレーションを1つのメソッドの実行で得ることができます。
用途としては、以下の様に全てのレコードが並んでいてそこからリレーションを行うものを選択して更新する場合に向いています。
[x] admin
[x] manager
[ ] normal
[ 更新 ]