見出し画像

Laravel 学習記録 #008 リレーションを学ぶ

Laravelのリレーションについて学習したものをまとめてます。

リレーションとは

  • データベーステーブル間の関連性を定義し、扱えるようにするもの

  • リレーションによってクエリを効率的に実行できる

  • Eloquentモデルクラスのメソッドとして定義する

  • リレーションの主なタイプには一対一、一対多、多対多がある

リレーションあり、なしの違い

例えば ユーザーテーブルとプロフィールテーブルがあり
リレーションを設定しないとすると以下のような手順で取得の必要がある
1.ユーザー情報を取得
2.そのデータを元に対応データを取得

// ユーザー情報を取得
$user = User::find(1);

// 対応するプロフィール情報を取得
$profile = Profile::where('user_id', $user->id)->first();

対して、リレーションがあれば
ユーザー情報を取得すれば、関連づけられたプロフィール情報も取得することができる

// リレーションを利用してユーザーとプロフィール情報を取得
$user = User::find(1);
$profile = $user->profile;


使い方

各モデルで紐づくモデルとの関係を専用のメソッドで定義します。
マニュアル見ながら学習しているので正しい説明はこちらを見てください。
https://readouble.com/laravel/10.x/ja/eloquent-relationships.html

一対一のリレーション

単一のモデルが単一の子モデルと紐づくリレーション。
Userモデルが1つのPhoneモデルに関連づけられている場合
UserモデルとPhoneモデルのそれぞれにメソッドを定義します。

Userモデルの定義:
phoneメソッドを作成し、hasOneメソッドによって関連づけを定義

/**
 * ユーザーに関連している電話の取得
 */
public function phone(): HasOne
{
    return $this->hasOne(Phone::class);
}
  • 第一引数: 関連するモデルクラスの名前を指定。例: Phone::class

  • 第二引数: 外部キー名を指定。関連モデルの外部キーとして使用
    るデータベースカラムの名前。
    デフォルト(指定しない場合)は<モデル名_id>で想定されます(この場合user_id)

  • 第三引数: ローカルキー(親モデルの主キーカラム)を指定。指定しない場合は id 。異なる主キーカラムを使用する場合に指定します。

// 引数指定の例
return $this->hasOne(Phone::class); // 第一引数のみ指定
return $this->hasOne(Phone::class, 'custom_foreign_key'); // 第一引数と第二引数を指定
return $this->hasOne(Phone::class, 'custom_foreign_key', 'custom_primary_key'); // 全ての引数を指定


Phoneモデルの定義:
userメソッドを作成し、belongsToメソッドによって関連づけを定義

/**
 * この電話を所有しているユーザーの取得
 */
public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}
  • 第一引数: 関連するモデル(親モデル)のクラス名を指定。例: User::class

  • 第二引数: 親モデル内の外部キー名を指定。指定がない場合は子モデルの<メソッド名 _id>となる。例: userメソッドの場合user_id。

  • 第三引数: 親モデル内の主キー名を指定。通常は id。


一対多のリレーション

単一のモデルが1つ以上の子モデルと紐づくリレーション。
Postモデルが複数のCommentモデルの親である関係を定義の場合
PostモデルとCommentモデルのそれぞれにメソッドを定義します。

Postモデルの定義:
commentsメソッドを作成し、hasManyメソッドによって関連づけを定義

/**
 * ブログポストのコメントを取得
 */
public function comments(): HasMany
{
    return $this->hasMany(Comment::class);
}

※引数はhasOneと同様

Commentモデルの定義:
postメソッドを作成し、belongsToメソッドによって関連づけを定義

/**
 * コメントを所有している投稿を取得
 */
public function post(): BelongsTo
{
    return $this->belongsTo(Post::class);
}


多対多のリレーション

モデルが複数の子モデルと紐づき、同様に関連モデルも複数の親モデルに関連付けられるリレーション

親モデル、子モデルの他に中間テーブルを用意する必要があり
中間テーブルは関連付けたいモデル名をアルファベット順でスネークケースで繋げた命名とする。
例:users、roles、role_userの3つのテーブルの場合
role_user テーブルは中間テーブルとして役割(roles)とユーザー(users)を関連付ける。
中間テーブルには、関連モデルの外部キーを格納し、両方のモデルを関連付ける。
リレーションの定義は中間テーブル以外の関連モデルに定義する。

Userモデルの定義:
rolesメソッドを作成し、belongsToManyメソッドによって関連づけを定義

/**
* このユーザーに属する役割
*/
public function roles(): BelongsToMany
{
    return $this->belongsToMany(Role::class);
}
  • 第二引数:中間テーブル名を指定。指定がない場合は命名規則通りになる。

  • 第三引数: 第三引数は関係を定義しているモデルの外部キー名

  • 第四引数: 関連付けるモデルの外部キー名 

//例)
return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');


Roleモデルの定義:
usersメソッドを作成し、belongsToManyメソッドによって関連づけを定義

/**
 * この役割に属するユーザー
 */
public function users(): BelongsToMany
{
    return $this->belongsToMany(User::class);
}


こんな感じで定義できます。
以上で基本的なリレーションの設定はOKです。
多対多の中間テーブルの操作に関しても機能が用意あるので、調べながら使っていきたいです。

この記事が気に入ったらサポートをしてみませんか?