PHP/Laravel

【Laravel】1対多のテーブルリレーション・hasMany/belongsToとは?

Laravel-hasMany-belongsTo

Laravelでテーブルのリレーションを定義するhasManyとbelongsToの理解に時間がかかったので、整理がてらまとめてみました。

 

この記事は、テーブル・レコード・カラム・SQLの基本は理解しているけど、テーブルリレーションって何?hasMany?belongsToがよくわからんぞ、という人向けに書いています

 

1対多(1対N)のリレーションとは?

「著者」と「本」の関係を例に見ていきましょう。

小説家・東野圭吾さんは、たくさんの本を書いています。

  • 白夜行
  • 容疑者Xの献身
  • マスカレードホテル
  • 夢幻花
    ・・・他多数

「1人の小説家が、多数の本を書いている」

これが「1対多」の関係です。

テーブルとサンプルデータの作成

2つのテーブルを作成します。

  • 著者の情報を格納するテーブル:authors
  • 本のタイトルを格納するテーブル:books

各テーブルのカラムとレコードを下記のように作ります。

Laravel-hasMany-belongsTo6

テーブルとモデルのマッピング

「モデル」とは、テーブルの内容を定義したクラスです。モデルをテーブルに紐づけることで、テーブル操作が簡単にできます。

テーブルのカラム(フィールド)を、プロパティとして持たせているので、テーブルをインスタントして扱うことができます。

SQLをゴリゴリ書かなくても、レコードの抽出・挿入・更新・削除が簡単にできるのです。

1つのテーブルにつき、1つのモデルが紐づきます。Laravelにはテーブルとモデルを紐づける命名規則があります。

Laravelでは、「テーブル」と「モデル」を自動でマッピングするための命名規則があります。

モデル名=単数形/テーブル名=複数形で命名すると、自動でマッピングされます。

(例)

  • モデル名=Book
  • テーブル名=books

この命名規則を破ったネーミングにする場合、特別な記述をするとマッピングできます(この方法は当記事ではふれません)

たとえば、「people」という名前でテーブルを作成した場合、それに紐づけるモデル名は「Person」です。Personはpeopleの単数形ですからね!(むずかしい!)

Laravelの命名規則に従い、テーブルとモデルを作成します。

  • authorsテーブル ⇔ Authorモデル
  • booksテーブル ⇔ Bookモデル
Laravel-hasMany-belongsTo5-2

リレーション元・リレーション先

テーブルにリレーションがある場合、リレーション元(主)・リレーション先(従)という考え方をします。

  • リレーションテーブル=authorsテーブル
  • リレーションテーブル=booksテーブル

これもLaravelの命名規則があります。

  1. リレーションモデルのidカラム
  2. リレーションモデルの、[リレーションモデル名_id]カラム
Laravel-hasMany-belongsTo5

この規則により、2つのテーブルはこのような関係になります。

Laravel-hasMany-belongsTo7

リレーションを定義するメソッド

【1対多】のリレーションを定義するメソッドがあります。

  • hasManyメソッド 【1対多】のリレーションを定義する
    →【1】側で定義する(Authorモデル)
  • belongsToメソッド 【1対多】の逆向きのリレーションを定義する
    →【多】側で定義する(Bookモデル)

 

う~ん、なんかいまいちピンとこないなぁ~
もり
もり
まずは英語の復習からいくよ~!

hasManyのイメージ

“has”は、~を持っているという意味の動詞”have”の三人称単数形です。

もり
もり
ポイントは単数形だよ!
Laravel-hasMany-belongsTo1

池井戸潤さんも、本をたくさん書いていますね。同じく「1:多」の関係です。

Laravel-hasMany-belongsTo2

belongsToのイメージ

【1対多】の関係を、【多】である「本」の立場から見てみましょう。

「本」は、かならず、ひとりの著者に所属します。

たとえば、『白夜行』というタイトルの本は、「東野圭吾」さんの本です。

Laravel-hasMany-belongsTo3

『容疑者Xの献身』というタイトルの本も、「東野圭吾」さんの本です。

『七つの会議』というタイトルの本は、「池井戸潤」さんの本です。

Laravel-hasMany-belongsTo4

これが【1対多】の「逆向きのリレーション」の考え方です。

モデルの作成

下記のコマンドでAuthorモデルとBookモデルを作成します。

app配下に、Author.phpとBook.phpが作成されます。

Authorモデル(hasMany結合)

hasManyメソッドを使用して、Bookモデルと【1対多】のリレーションを定義します。

Bookモデル(belongsTo結合)

belongsToメソッドを使用して、Authorモデルと【1対多】の逆向きのリレーションを定義します。

 

これで、AuthorモデルとBookモデルに「リレーション」ができました。

リレーションを使用したレコード取得

動作確認用にテーブルにデータを作成します。

 

tinkerを起動して名前空間を定義します。

booksテーブル:id(7)の本の著者を取得する

booksテーブルのid=7は『七つの会議』です。『七つの会議』の著者は「池井戸潤」です。

 

想定どおり「池井戸潤」が取得できました。

コードを詳しくみてみましょう。

Laravel-hasMany-belongsTo8-0

①Book::find(7)

Bookモデルはbooksテーブルに紐づいています。Bookモデルを通して、booksテーブルのid=7のレコードを取得します。

Laravel-hasMany-belongsTo8-1

②Book::find(7)->author

Bookモデルに定義したauthorメソッドを呼び出します。

【1対多】の逆向きリレーション(belongsTo)で、authorsテーブルのレコードが取得できます。
※「authorsテーブルのid」と「booksテーブルのauthor_id」が紐づいていましたね

Laravel-hasMany-belongsTo8-2

③Book::find(7)->author->name

Authorモデルのnameプロパティを取得します。これは、authorsテーブルのnameカラムです。

Laravel-hasMany-belongsTo8-3

これが、リレーションを使用した値の取得方法です。

authorsテーブル:id(1)の著者の本の一覧を取得する

authorsテーブルのid=1は「東野圭吾」です。著者が「東野圭吾」の本をすべて取得します。

 

コードをみていきましょう。

Laravel-hasMany-belongsTo9-0

①Author::find(1)

Authorモデルはauthorsテーブルと紐づいています。Authorモデルを通して、authorsテーブルのid=1のレコードを取得します。

Laravel-hasMany-belongsTo9-1

②Author::find(1)->books

Authorモデルに定義したbooksメソッドを呼び出します。Authorに紐づくすべてのbookを取得します。

Laravel-hasMany-belongsTo9-2

このように、テーブルリレーションを定義することで、テーブルのCRUD操作が簡単にできるのです。

Laravelオススメ本

もり
もり
私はこの2冊で勉強してるよ~