L

リレーション — テーブル同士をつなぐ

「ユーザーと投稿」のように関連するテーブル同士をEloquentのリレーションでつなぐLaravelの基本を、やさしく解説します。

広告枠(記事上)— 本番では AdSense 広告が表示されます

実際のアプリでは、複数のテーブルが関連し合います。たとえば「1人のユーザーが、複数の投稿を持つ」といった関係です。Eloquent では、こうしたテーブル同士のつながりを リレーション として簡単に扱えます。

どんな関係かを考える

「ユーザー(users)」と「投稿(posts)」を例にします。

  • 1人のユーザーは、複数の投稿を持つ
  • 1つの投稿は、1人のユーザーに属する

この「1対多」の関係を、Eloquent では次の2つの言葉で表します。

  • ユーザーから見て「投稿をたくさん持つ」→ hasMany(ハズメニー)
  • 投稿から見て「ユーザーに属する」→ belongsTo(ビロングストゥ)

つなぐ目印:外部キー

テーブル同士をつなぐには、「どの投稿が、どのユーザーのものか」を記録する列が必要です。posts 表に user_id(ユーザーのID) という列を用意します。これを 外部キー と呼びます。

マイグレーションでは次のように追加します。

$table->foreignId('user_id')->constrained();

これで「posts.user_idusers.id を指す」というつながりが作られます。

モデルにリレーションを書く

User モデル(1人 → 複数の投稿)

// app/Models/User.php
public function posts()
{
    return $this->hasMany(Post::class);
}

Post モデル(1つ → 1人のユーザー)

// app/Models/Post.php
public function user()
{
    return $this->belongsTo(User::class);
}

使ってみる

リレーションを書くと、関連データをプロパティのように取り出せます。

// あるユーザーの投稿一覧
$user = User::find(1);
$posts = $user->posts;   // そのユーザーの投稿が全部取れる

// ある投稿の投稿者
$post = Post::find(1);
$author = $post->user;   // その投稿を書いたユーザー
echo $author->name;

$user->posts() のように関係を定義しておくだけで、$user->posts でつながったデータが取れる——これがリレーションの便利さです。

「N+1問題」を避ける:with()

一覧で「各投稿の投稿者名」を表示すると、投稿の数だけデータベースへ問い合わせが走り、遅くなることがあります(これを N+1問題 と呼びます)。with() で関連データをまとめて先に読み込むと解決します。

// 投稿と、その投稿者をまとめて取得
$posts = Post::with('user')->get();

今は「一覧で関連データを使うときは with() を付けると速い」とだけ覚えておけば十分です。

まとめ

  • 関連するテーブルは リレーション でつなぐ。
  • 「1対多」は、親に hasMany、子に belongsTo を書く。
  • つなぐ目印が 外部キー(例: posts.user_id)。foreignId('user_id')->constrained() で作る。
  • 定義すると $user->posts$post->user で関連データを取得できる。
  • 一覧では with() を使って N+1問題を防ぐ。
  • 第5章は完了です。次章では、ユーザーからの入力を受け取るフォームとバリデーションを学びます。
広告枠(記事下)— 本番では AdSense 広告が表示されます