リレーション、わかっているつもりでも設計しようとする時によく混乱するのでまとめ。
1対1
hasOne。(あまり使ったことない。)
Userが親モデル(主)。
Phoneが子モデル(従)。子モデルが user_id
カラムを持つ。(親モデル名_id)。親モデルの「スネークケース」名に「_id」
親も子も名前は単数形。
class User extends Model
{
/**
* ユーザーに関連している電話の取得
*/
public function phone()
{
return $this->hasOne(Phone::class);
}
}
class Phone extends Model
{
/**
* phonesテーブルにuser_idカラムが必要
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
外部キーがuser_id
で無い場合は第2引数にカスタムキー名を渡す。
class Phone extends Model
{
public function user()
{
return $this->belongsTo(User::class, 'foreign_key');
}
}
1対多(One to Many)
hasMany。メソッドの名前を複数形にする必要あり。
親モデル hasMany 子モデル。もしくは Class 〇〇 hasMany 子モデルと考えると混乱しづらい。
class User extends Model
{
/**
* 名前を複数形にする
*/
public function phones()
{
return $this->hasMany(Phone::class);
}
}
belongsToは1対1の場合と同じ。単数形のメソッド名。
class Phone extends Model
{
/**
* phonesテーブルにuser_idカラムが必要
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
多対多(Many to Many)
中間テーブル(pivot table)が必要。メソッド名はお互いに複数形。belongsToMany。
テーブルは合計3つ必要。
中間テーブル作成。それぞれのテーブルの単数形(モデル名)をアルファベット順に並べる。
php artisan make:migration create_category_product_table --create=category_product
それぞれの中身。category_productがそれぞれのテーブルの_idを持つ。これでProduct、Categoryどちらからも呼び出せる。
products
id - integer
name - string
categories
id - integer
name - string
category_product
category_id - integer
product_id - integer
メソッド名はお互いに複数形。
class Product extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
class Category extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
}
attach
、detach
、sync
メソッドなどが使える。
Have a good relationship with relationships.