はじめに
以下記事はリレーション関係を構築したテーブルからデータを効率的に取得できるWithメソッドを使う手順のメモになります
親テーブルと子テーブルの見分け方
親テーブルと子テーブルを見分けるためのポイントは以下の通りです。
外部キーの有無
子テーブルは必ず外部キーを持ちます。
これは親テーブルのプライマリーキーを参照するカラムです。
リレーションシップの方向
親テーブルは他のテーブルに参照されるため、リレーションシップの出発点となります。
子テーブルは親テーブルを参照し、その情報を持っています
1対1の場合
1対1のリレーションでは、一つのモデルが一つの関連モデルを持つ関係を表します。以下は、Userモデル
が一つのProfileモデル
を持つ場合です。
// User.php
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
// Profile.php
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
データの取得
$user = User::with('profile')->find($id);
指定したユーザーIDのユーザーとそのユーザーのプロフィールが取得できます
1対多の場合
1対多のリレーションでは、一つの親モデルが複数の子モデルを持つ関係を表します。以下は、Userモデル
が複数のPostモデル
を持つ場合です。
// User.php
class User extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
}
// Post.php
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
データの取得
User
と関連するPost
を同時に取得するには、以下のようにwithメソッド
を使用します
$user = User::with('posts')->find($id);
これにより、指定したユーザーIDのユーザーとそのユーザーの全ての投稿が取得できます。
多対多
多対多のリレーションでは、複数のモデルが他の複数のモデルと関連している関係を表します。以下はPostモデルが複数のTagモデルを持ち、Tagモデルも複数のPostモデルを持つ場合です。
// Post.php
class Post extends Model
{
public function tags()
{
return $this->belongsToMany(Tag::class);
}
}
// Tag.php
class Tag extends Model
{
public function posts()
{
return $this->belongsToMany(Post::class);
}
}
データの取得
$post = Post::with('tags')->find($id);
指定した投稿IDの投稿とその投稿に関連する全てのタグが取得できます
複数のリレーションが存在する場合
以下の例のように1つのモデルに対して複数のリレーションが設定されている場合、Withメソッドでデータを取得するには以下のようにコードを記述します
-
Userモデル
- 1対多のリレーションでPostモデルを持つ
- 1対1のリレーションでProfileモデルを持つ
-
Postモデル
- 多対多のリレーションでTagモデルを持つ
// User.php
class User extends Model
{
public function posts()
{
//(1人のユーザーが複数の投稿を持つ)
return $this->hasMany(Post::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
}
// Profile.php
class Profile extends Model
{
public function user()
{
//(1人のユーザーに1つのプロフィールがある)
return $this->belongsTo(User::class);
}
}
// Post.php
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function tags()
{
//(1つの投稿が複数のタグを持ち、1つのタグが複数の投稿に関連する)
return $this->belongsToMany(Tag::class);
}
}
// Tag.php
class Tag extends Model
{
public function posts()
{
return $this->belongsToMany(Post::class);
}
}
Withメソッドの使い方
複数のリレーションを一度に取得するためには、withメソッドにリレーション名をカンマで区切って指定します。
※ リレーション名とはモデルに記載したメソッド名
を指します
$user = User::with(['posts.tags', 'profile'])->find($id);
Withメソッドの補足
User::with()
ユーザーモデルを基にリレーションを取得します。
['posts.tags', 'profile']
postsリレーションの中にあるtagsリレーションと、profileリレーションを指定しています。
find($id)
特定のユーザーIDを指定して、そのユーザーと関連するデータを取得します。
取得できるデータ
- ユーザー情報
- そのユーザーが持つ全ての投稿情報
- 各投稿が持つ全てのタグ情報
- そのユーザーのプロフィール情報
まとめ
ithメソッドを使うことで、複数のリレーションを一度に効率的に取得することができ、パフォーマンスが向上します