リレーション — テーブル同士をつなぐ
「ユーザーと投稿」のように関連するテーブル同士を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_id は users.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 広告が表示されます