Pivotモデルについて一瞬つまづいたポイントメモ
この記事はPivotモデルを利用した多対多構成が、普通にドキュメントを読んでもわかりづらかったので自分的にわかりやすくしたメモです。
想定構成はPHP7 laravel5.5となっております。
なお、基本的に以下のページを参照しています。
おそらく躓きそうなことの8割は以下のページを見れば解決するかと思います。
Laravel 5.5 Eloquent:リレーション
Pivot tables and many-to-many relationships
Pivotテーブルの名称を特殊なものにしたい。
pivotテーブルの名称をLaravel標準のlogal_forginではなく、自分で作成した名称のものにしたいとき、belongsToManyの第二引数にテーブル名を与えると行うことができる。
public function users()
{
return $this->belongsToMany('App\Role', 'role_user');
}
Eloquentではクラスのプライベート変数にテーブル名を宣言することができるため、以下のようにやりたくなるが、それは正しくない。
<?php
namespace App
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
public function users() {
return $this->belongsToMany('App\Role')->using('App\RoleUser');
}
}
<?php
namespace App
use Illuminate\Database\Eloquent\Relations\Pivot;
class RoleUser extends Pivot {
protected $table = "role_user";
}
Pivotモデルは以下のように呼び出す場合にデータが格納されるモデルの指定であり、取得系には関係がない。
たとえPivotモデルでテーブル名を指定してあっても、実際に呼び出しているEloquentモデル側で指定してあるDBテーブル名が間違えていれば容赦なく呼び出しに失敗する。
pivotモデルを利用したテーブルの指定方法があったら教えてください。複数個所で同一テーブル名指定したくないです……
$roles = Role::find(1)->users;
foreach ($users as $user) {
debug($user->pivot);
}
また、たとえpivotテーブルをモデルとして指定してあっても、pivotテーブル内の他のデータを取得するためにはリレーション指定の時点で指定していなければ呼び出すことができない。
<?php
namespace App
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
public function users() {
return $this->belongsToMany('App\Role', 'role_user')->using('App\RoleUser');
}
}
$roles = Role::find(1)->users;
foreach ($users as $user) {
debug($user->pivot->flag); //null
}
以下のようにすれば呼び出せる。
<?php
namespace App
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
public function users() {
return $this->belongsToMany('App\Role', 'role_user')->using('App\RoleUser')->withPivot("flag");
}
}
$roles = Role::find(1)->users;
foreach ($users as $user) {
debug($user->pivot->flag); //1
}
しかしこのように指定した場合、べつにPivotモデルを指定していなくても値は同様に呼び出すことができる。
<?php
namespace App
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
public function users() {
return $this->belongsToMany('App\Role', 'role_user')->withPivot("flag");
}
}
$roles = Role::find(1)->users;
foreach ($users as $user) {
debug($user->pivot->flag); //1
}
結論
結局Pivotテーブルを使う意味はあるのだろうか?
おそらく複雑な更新などを行いたいときに、モデル内に関数を増やしたい……などの時に使うことができるのかもしれないが、多対多構成用の更新メソッドも簡単なのはLaravel標準でついているため、そうとう複雑ではない限りは使うことはないように思う。(個人の感想です)
少なくとも「同じテーブル名を複数箇所で宣言したくない」という程度の用途には向かないことが判明したため、涙を呑んでモデルを削除することにする。