【Laravel】Withメソッドの使い方（リレーション）

# はじめに
以下記事はリレーション関係を構築したテーブルからデータを効率的に取得できるWithメソッドを使う手順のメモになります

## 親テーブルと子テーブルの見分け方
親テーブルと子テーブルを見分けるためのポイントは以下の通りです。

### 外部キーの有無

子テーブルは必ず外部キーを持ちます。
これは親テーブルのプライマリーキーを参照するカラムです。
### リレーションシップの方向
親テーブルは他のテーブルに参照されるため、リレーションシップの出発点となります。
子テーブルは親テーブルを参照し、その情報を持っています

## 1対1の場合
1対1のリレーションでは、一つのモデルが一つの関連モデルを持つ関係を表します。以下は、`Userモデル`が一つの`Profileモデル`を持つ場合です。

```Model.php
// 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);
    }
}
```
### データの取得
```***controller.php
$user = User::with('profile')->find($id);
```
指定したユーザーIDのユーザーとそのユーザーのプロフィールが取得できます

## 1対多の場合

1対多のリレーションでは、一つの親モデルが複数の子モデルを持つ関係を表します。以下は、`Userモデル`が複数の`Postモデル`を持つ場合です。

```Model.php

// 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メソッド`を使用します
```***controller.php
$user = User::with('posts')->find($id);
```
これにより、指定したユーザーIDのユーザーとそのユーザーの全ての投稿が取得できます。

## 多対多
多対多のリレーションでは、複数のモデルが他の複数のモデルと関連している関係を表します。以下はPostモデルが複数のTagモデルを持ち、Tagモデルも複数のPostモデルを持つ場合です。
```Model.php
// 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);
    }
}

```
### データの取得

```***controller.php
$post = Post::with('tags')->find($id);
```
指定した投稿IDの投稿とその投稿に関連する全てのタグが取得できます

## 複数のリレーションが存在する場合
以下の例のように１つのモデルに対して複数のリレーションが設定されている場合、Withメソッドでデータを取得するには以下のようにコードを記述します

- **Userモデル**

    - 1対多のリレーションでPostモデルを持つ
    - 1対1のリレーションでProfileモデルを持つ
- **Postモデル**

    - 多対多のリレーションでTagモデルを持つ
```Model.php
// 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メソッドにリレーション名をカンマで区切って指定します。
※ リレーション名とはモデルに記載した`メソッド名`を指します
```***controller.php
$user = User::with(['posts.tags', 'profile'])->find($id);
```
### Withメソッドの補足
#### User::with()
ユーザーモデルを基にリレーションを取得します。
#### ['posts.tags', 'profile']
postsリレーションの中にあるtagsリレーションと、profileリレーションを指定しています。
#### find($id)
特定のユーザーIDを指定して、そのユーザーと関連するデータを取得します。

##### 取得できるデータ
- ユーザー情報
- そのユーザーが持つ全ての投稿情報
- 各投稿が持つ全てのタグ情報
- そのユーザーのプロフィール情報

## まとめ
ithメソッドを使うことで、複数のリレーションを一度に効率的に取得することができ、パフォーマンスが向上します