リレーションとは
データベースのテーブルは互いに関連し合っていることがよくあります。たとえば、ブログ投稿には多数のコメントがあったり、注文はそれを行ったユーザーに関連していたりします。 Eloquentはこうしたテーブル間の関連(リレーション)を簡単に定義・操作する仕組みを提供しています。リレーションはEloquentモデルのメソッドとして定義します。このページでは
User、Post、Comment、Tag などの具体的なモデルを例として使います。
これらのモデルとテーブルはあらかじめ作成されている前提で進めます。hasOne(1対1)
hasOne は、あるモデルが別のモデルを1つだけ持つ関係を表します。たとえば User が1つの Profile を持つ場合です。
リレーションの定義
User モデルに profile メソッドを定義します。
profiles テーブルに user_id カラムがあると想定します。
関連データの取得
定義したリレーションはプロパティとしてアクセスできます。belongsTo(1対1の逆)
belongsTo は hasOne の逆で、外部キーを持つ側のモデルに定義します。Profile が User に属する関係を表します。
リレーションの定義
_id を付けたカラム名(この場合 user_id)を外部キーとして使います。
関連データの取得
hasMany(1対多)
hasMany は、1つの親モデルが複数の子モデルを持つ最もよく使われるリレーションです。たとえば、1つの Post が複数の Comment を持つ場合です。
リレーションの定義
comments テーブルに post_id カラムがあると想定します。
関連データの取得
hasMany のリレーションはコレクションを返します。
逆のリレーション(belongsTo)
コメントから投稿を参照するには、Comment モデルに belongsTo を定義します。
belongsToMany(多対多)
多対多リレーションは、両方のモデルが互いに複数の関連を持つ場合に使います。たとえば、Post が複数の Tag を持ち、Tag も複数の Post に属する場合です。
テーブル構造
多対多には中間テーブルが必要です。Post と Tag の場合、post_tag という中間テーブルを用意します。
中間テーブル名はEloquentが関連する2つのモデル名をアルファベット順に結合して自動的に推測します(
post + tag → post_tag)。リレーションの定義
Tag 側にも同様に定義することで、逆方向からも参照できます。
関連データの取得
関連データの追加・削除
attach で中間テーブルにレコードを追加、detach で削除します。
Eagerローディング
N+1問題とは
リレーションをプロパティとしてアクセスすると、Eloquentはその都度クエリを発行します。これを「遅延ロード(Lazy Loading)」といいます。ループ内でリレーションにアクセスすると、N+1問題が発生します。with()によるEagerローディング
with() メソッドを使うと、関連データをまとめて取得できます。これにより、クエリが2回だけに抑えられます。
複数のリレーションを同時にEagerロード
配列で複数のリレーションを指定できます。ネストしたEagerロード
ドット記法でネストしたリレーションもEagerロードできます。次のステップ
Eloquent入門
Eloquentの基本的なCRUD操作に戻って復習します。