Skip to main content

リレーションとは

データベースのテーブルは互いに関連し合っていることがよくあります。たとえば、ブログ投稿には多数のコメントがあったり、注文はそれを行ったユーザーに関連していたりします。 Eloquentはこうしたテーブル間の関連(リレーション)を簡単に定義・操作する仕組みを提供しています。リレーションはEloquentモデルのメソッドとして定義します。
このページでは UserPostCommentTag などの具体的なモデルを例として使います。 これらのモデルとテーブルはあらかじめ作成されている前提で進めます。
Eloquentが対応する主なリレーションは以下のとおりです。

hasOne(1対1)

hasOne は、あるモデルが別のモデルを1つだけ持つ関係を表します。たとえば User が1つの Profile を持つ場合です。

リレーションの定義

User モデルに profile メソッドを定義します。
Eloquentは親モデル名をもとに外部キーを自動的に推測します。この場合、profiles テーブルに user_id カラムがあると想定します。

関連データの取得

定義したリレーションはプロパティとしてアクセスできます。
リレーションメソッドをプロパティとして呼び出すと、Eloquentが自動的にクエリを発行して関連データを返します。これを「ダイナミックリレーションプロパティ」といいます。

belongsTo(1対1の逆)

belongsTohasOne の逆で、外部キーを持つ側のモデルに定義します。ProfileUser に属する関係を表します。

リレーションの定義

Eloquentはリレーションメソッド名に _id を付けたカラム名(この場合 user_id)を外部キーとして使います。

関連データの取得

hasMany(1対多)

hasMany は、1つの親モデルが複数の子モデルを持つ最もよく使われるリレーションです。たとえば、1つの Post が複数の Comment を持つ場合です。

リレーションの定義

Eloquentは comments テーブルに post_id カラムがあると想定します。

関連データの取得

hasMany のリレーションはコレクションを返します。
クエリに条件を追加することもできます。

逆のリレーション(belongsTo)

コメントから投稿を参照するには、Comment モデルに belongsTo を定義します。

belongsToMany(多対多)

多対多リレーションは、両方のモデルが互いに複数の関連を持つ場合に使います。たとえば、Post が複数の Tag を持ち、Tag も複数の Post に属する場合です。

テーブル構造

多対多には中間テーブルが必要です。PostTag の場合、post_tag という中間テーブルを用意します。
中間テーブル名はEloquentが関連する2つのモデル名をアルファベット順に結合して自動的に推測します(post + tagpost_tag)。

リレーションの定義

Tag 側にも同様に定義することで、逆方向からも参照できます。

関連データの取得

関連データの追加・削除

attach で中間テーブルにレコードを追加、detach で削除します。
sync を使うと、指定したID以外の中間テーブルレコードを自動的に削除して、渡したIDだけが関連として残るように更新します。

Eagerローディング

N+1問題とは

リレーションをプロパティとしてアクセスすると、Eloquentはその都度クエリを発行します。これを「遅延ロード(Lazy Loading)」といいます。ループ内でリレーションにアクセスすると、N+1問題が発生します。
投稿が100件あれば、合計101回のクエリが発行されます。これはパフォーマンスに大きな影響を与えます。

with()によるEagerローディング

with() メソッドを使うと、関連データをまとめて取得できます。これにより、クエリが2回だけに抑えられます。
実行されるSQLは以下の2つだけです。

複数のリレーションを同時にEagerロード

配列で複数のリレーションを指定できます。

ネストしたEagerロード

ドット記法でネストしたリレーションもEagerロードできます。
EagerローディングはN+1問題を防ぐために非常に重要です。ループ内でリレーションにアクセスするときは、常に with() を使う習慣をつけましょう。

次のステップ

Eloquent入門

Eloquentの基本的なCRUD操作に戻って復習します。
最終更新日 2026年4月10日