LaravelのEloquentリレーションとは?1対1についてのまとめ

LaravelのEloquentリレーションとは?1対1についてのまとめ

1010 回閲覧されました

みなさんこんにちは、jonioです。

LaravelにEloquentリレーションがありますが理解が甘かったのでちゃんと勉強してまとめました。

リレーションとは何かと1対1についてまとめます。

 

リレーションとは

データベース上のテーブルとテーブルを結ぶものです。

例えばあるユーザーが記事を投稿するのでユーザーの情報を入れたテーブルと投稿情報を入れたテーブルを紐付けるとします。

こんな場合にリレーションを使いますがリレーションを使えば紐づけたUserテーブルからPostテーブルの内容を引っ張ったりPostテーブルからUserテーブルの内容を引っ張って来る事ができます。

具体的なコードで実際に起きている事を見た方が早いので見ていきましょう。

 

1対1

例えば会員ユーザーテーブルとユーザーのメールアドレスがあるメールテーブルを紐づけるとします。

会員1人に対してメールアドレスは普通は1つです。

この様に1人に対して1つのメールアドレスが対応する関係を1対1のリレーションと言います。

ユーザーテーブルとメールアドレステーブルの図を↓とします。

テーブル同士を繋ぐ時は主キーと外部キーで繋ぎますが大元のテーブルのidを主キーとします。(上の図の青枠)

そして結び付けられるテーブルに外部キーのカラムを作るのですが命名規則があり「大元のテーブル名_id」です。

普通はユーザーにメールアドレスを結びつけるからUserテーブルを大元のテーブルと考えるのが普通なので外部キーのカラム名が「user_id」になります。(上の図の赤枠)

それでは実際のテーブルを書きますが↓で考えます。

 

1対1のコードの書き方

UserモデルとMailモデルとそれぞれのマイグレーションファイルを作成をしてテーブルの内容を↓にしたとします。

コードの書き方ですが下記の様に2通りあります。

  1. 主キーがあるテーブルから外部キーがあるテーブルの情報を引っ張る
  2. 外部キーがあるテーブルから主キーがあるテーブルの情報を引っ張る

まずは主キーがあるテーブルから外部キーがあるテーブルの情報を引っ張りますが「主キーがあるテーブル」・「外部キーがあるテーブル」の言葉が長いので「主キーがあるテーブル」をとして「外部キーがあるテーブル」を子とします。

1と2は共にテーブルの情報を引っ張るための記述をモデルにしないといけません。

 

親から子の情報を引っ張る

親のモデルは「Laravelのプロジェクト > app > Models > User.php」にあります。

コードを↓にします。

7行目の「email」ですが子のテーブル名を小文字にして書きます。(ルールではないですが一般的にそうするみたいです)

今はEmailだから「email」になります。

8行目は「return $this->hasOne(子のモデル名::class); 」と書きます。

外部キーがあるモデル名はEmailなので8行目は「return $this->hasOne(Email::class); 」となります。

hasOne」ですが1人のユーザーが1つのemailを持っているから1つを持つのでhasOneと考えると覚えやすいと思います。

これで親から子の情報を引っ張ってこれるようになりました。

 

子の情報を表示

コントローラーに↓の記述をします。(どのページを表示するかのルーティングの設定はしたとします)

9行目の「User::find(2)->email->email;」のUser::find(2)ですが「モデル名::find(主キーのid)」でレコードの情報を取得できます。

今だとUserテーブルのidが2のレコードを取得するという意味です。

「User::find(2)->email->email;」のemailですがこれは外部キーがあるEmailテーブルの事でemail

は親(Userテーブル)のidの番号に対応する子(Emailテーブル)のuser_idの番号のemailカラムの値という意味です。

Userテーブルのidは2でそれに対応するEmailテーブルのuser_idは2なのでuser_idが2のemailの値という意味です。(Userテーブルのidが3でそれに対応するEmailテーブルのuser_idは3と言った感じです)

だから「bbb@gmail.com」を取得します。

そしてyyy.blade.phpで「{{email}}」と記述すると「bbb@gmail.com」が表示されます。

 

子から親の情報を引っ張る

Emailテーブルのモデルは「Laravelのプロジェクト > app > Models > Email.php」にあります。

コードを↓にします。

7行目の「user」ですが親テーブル名を小文字にして書きます。

8行目は「return $this->belongsTo(親のモデル名::class); 」と書きます。

親のモデル名はUserなので8行目は「return $this->belongsTo(User::class); 」となります。

belongsTo」ですがemailがユーザーに所属するからbelongsToと考えると覚えやすいと思います。

これで子から親の情報を引っ張ってこれるようになりました。

 

親の情報を表示

コントローラーに↓の記述をします。(どのページを表示するかのルーティングの設定はしたとします)

9行目ですが親から子の情報を引っ張って来る時と考え方は全く同じです。

これでEmailテーブルのuser_idが1に対応するユーザーテーブルのidが1のnameカラムの値を引っ張って来ます。

取得した値は「user1」です。

そしてyyy.blade.phpで「{{name}}」と記述すると「user1」と表示されます。

 

外部キーの名前を変える場合

外部キーの名前は「大元のテーブル名_id」ですが別の名前にする事もできます。

先程使ったテーブルをもう一度見てみます。

外部キーが「user_id」ですが「user_mail」に変えたいとします。

この場合はUserモデルのmail関数が↓に変わります。

6行目の「class」の後ろに「,’自分で名称を決めた外部キー‘」を付け加えます。

今は自分で名称を決めた外部キーが「user_mail」です。

また外部キーだけではなく主キーも変えたい場合もあると思いますがその場合はモデルのコードを↓にします。

主キーを「name」にしたとします。

6行目の「return $this->hasOne(Email::class,’user_mail’,’name‘);」のnameがidから変更した主キーです。

この様に主キーや外部キーを変える事はできますが下手に変えるとどのテーブルを繋いでいるのかが見えにくくなるので主キーは「id」で外部キーは「主キー_id」にした方がリレーションはやりやすいと思います。

次回ははリレーションの1対多についてのまとめです。