Laravel〜Eloquentリレーション〜

## はじめに
テーブルは自身で独立していることよりも他のテーブルを関係を持っていることが多い。
そのため、テーブル同士でリレーションを設定することで他のテーブルへのデータのアクセスが
可能となる。
今回は以下の４ケースについて紹介する。
1. 1対1
2. 1対多
3. 1対多（Inverse）
4. 多対多

## 1対1
まずは1対1で、例として公式ドキュメント同様に、userモデルとphoneモデルを挙げる。
ユーザー1人に対して、携帯電話が1台持っており、1台の携帯電話に対してユーザーは
1人なので1対1のリレーションを持っている。
まずは親モデル(userモデル)にhasOneメソッドを記載する。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function phone()
    {
        return $this->hasOne('App\Phone'); //第一引数にモデル名
    }
}
```

また、外部キーは自動で「親モデル_id」と指定されてしまうので、他のカラム名に変更したい場合は
第二引数を指定して、オーバーライドしてあげる。
主キーについても、「id」となっているので、第三引数で指定する。

```php:
    public function phone()
    {
        return $this->hasOne('App\Phone', 'hoge', 'hogehoge');
    }
```

リレーションが定義できたらEloquentの動的プロパティを使い、phoneモデルのレコードを取得できる。

```php:
$phone = User::find(1)->phone;
```

また、動的プロパティだけではなく、リレーションメソッドを返すことも可能である。
HasOne オブジェクトなどの Eloquent リレーションオブジェクトはクエリビルダとしても動作するので
便利。

```php:
$phone = User::find(1)->phone()->where('name', 'Iphone');
```

### 逆の関係
PhoneモデルからUserモデルへアクセスするためのリレーションを定義していく。今度は、belongsToメソッドを使っていく。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Phone extends Model
{
    public function user()
    {
        return $this->belongsTo('App\User'); //第一引数にモデル名
    }
}
```

hasOneメソッド同様に、外部キーは自動で「親モデル_id」と指定されてしまうので、他のカラム名に
変更したい場合は第二引数を指定し、主キーについても、「id」となっているので、第三引数で指定する。

## 1対多
続いて、1対多のケース。アマゾンなどのショッピングサイトのように一つの商品(productモデル)に対して、
複数のレビュー(reviewモデル)があるような状態である。
まずは親モデル(productモデル)から子モデル(reviewモデル)へのリレーションを定義する。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    public function reviews()
    {
        return $this->hasMany('App\Review');
    }
}
```

引数については1対1の時と同様である。必要であればオーバーライドする。
リレーション先へのアクセス方法も動的プロパティ、クエリビルダそれぞれで
アクセス可能である。

### 逆の関係
1対多の逆の関係、子モデル(reviewモデル)から親モデル(productモデル)へのリレーションを定義する際は、
1対1の時と同様にbelongsToメソッドを用いる。引数の考え方も同様。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Review extends Model
{
    public function product()
    {
        return $this->belongsTo('App\Product');
    }
}
```

## 多対多
多対多の例として、ユーザー(user)と趣味(hoby)をあげる。
1人のユーザに対して、趣味はスポーツ、映画、料理など複数ある。
また、その逆で、1つの趣味、例えばスポーツが趣味の人は複数人いる
場合が、この多対多の関係にあたる。

また、多対多の場合は、リレーションを定義する2つのテーブル意外に、その両方をつなぐ
中間テーブルを作成する必要がある、
以下、作成テーブル例である。

#### users
| id | name | 
|:----:|:----:|
| 1 | nobita |
| 2 | suneo |
| 3 | sizuka |
| 4 | doraemon |
| 5 | takeshi |

#### hobies
| id | category | 
|:----:|:----:|
| 1 | sports |
| 2 | cooking |
| 3 | movie |
| 4 | reading |
| 5 | shopping |

#### hoby_user(アルファベット順にする)
| user_id | hoby_id | 
|:----:|:----:|
| 1 | 2 |
| 2 | 1 |
| 3 | 3 |
| 3 | 5 |

まずは、usersテーブルからhobiesテーブルへアクセスするためにリレーションを定義していく。
belongsToManyメソッドを用いる。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function hobies()
    {
        return $this->belongsToMany('App\Hoby', 'hoby_user', 'user_id', 'hoby_id');
    }
}
```

- 第一引数： クラス名
- 第二引数： 結合テーブル名(中間テーブル)
- 第三引数： リレーションを定義しているモデルの外部キー名
- 第四引数： 結合するモデルの外部キー名

### 逆の関係
逆の関係も同様にbelongsToManyメソッドを用いる。

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Hoby extends Model
{
    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}
```

## 終わりに
今回はリレーションを定義する上で、基本的な4パターンを紹介しました。以下、3パターンについては
まだ習得できていないので、またの機会とさせていただきます。
中間テーブルについても、もう少し詳しくかければいいと思います。
- Has Many Through
- ポリモーフィックリレーション
- ポリモーフィック関係の多対多

## 参考サイト
[https://readouble.com/laravel/5.5/ja/eloquent-relationships.html#many-to-many](https://readouble.com/laravel/5.5/ja/eloquent-relationships.html#many-to-many)