0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravel〜Eloquentリレーション〜

Posted at

はじめに

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

  1. 1対1
  2. 1対多
  3. 1対多(Inverse)
  4. 多対多

1対1

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

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

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

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

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

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

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

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

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

逆の関係

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

<?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

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

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

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

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

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?