クマのブログ

つまづいたところ、学びを書いていきます

【Laravel】リレーション(1対多)

前提

背景

  • 会社の研修中、PHPの基礎講座を受講

  • 今の会社に就職前に独学でPHPを学習していたが、初めて知ったことがあったので、アウトプット

  • 先日Laravelのリレーションでつまづいたアウトプット(以下記事)の続き。

kuma-kuma0121.hatenablog.com

今回は「1対多」「多対多」のリレーションをアウトプット

  • テーブルとかカラムの前提は前回同様マニュアルに準じます。

参考

公式マニュアル

事象(やりたいこと)

2つのモデルを「1対多」の関係にしたい

「1対多」とは

1つのテーブルの要素に対して、別テーブルの複数の要素が従属している状態。例えばブログ1記事とそのブログに対するコメントの関係は「1対多」である

  • ブログ1記事には複数のコメントを投稿できる

 →ブログが1個決まればおのずとそれに追随するコメントも特定できる

  • 逆は違う(コメントが1つ決まったら1つのブログ記事しか紐づかない)

  • この状況が1対多の関係

 →今回でいうと、1(ブログ):多(コメント)の関係

前提

  • データベース内にはpostsテーブルとcommentsテーブルが分かれており、各テーブルのカラムは以下の通り
  • モデルもPostモデル、Commentモデルに準備

↓postsテーブル(ブログ記事)

カラム名 属性
id int
name string

↓commentsテーブル(コメント)

カラム名 属性
id int
post_id int
title string

実装方法

  • PostモデルからComentモデルを参照したい(=値を取得したい)のであればPostモデルの記述は以下の通り書いてリレーションを作れる
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}
  • 実際に値を取得する際は以下の通り。ここは前回の「1対1」の時と同じ。 ※ここではControllerで値を取得している。
use App\Models\Post;

$comments = Post::find(1)->comments; // Commentsテーブルの1行目のデータを取得
  • 「1対1」の時とほぼ同じですが、hasOnehasManyに変わっているだけ。

注意点(外部キーについて)

  • 外部キーについては前回記事でアウトプット済みなので、割愛。 今回は、commentsテーブルにpost_idがない場合、

  • hasOneとhasManyの使い分けがわかりにくければ、

ブログ1記事はたくさん(Many)のコメントを持てるからhasMany

ユーザー1人は1つ(One)の電話番号しか持てないから、hasOne

といった感じでイメージ付ける

逆の参照も同じ

  • 逆にCommentモデルからPostモデルを参照したい(=値を取得したい)ならば、前回同様belongsToを使用し、参照先を変更。

  • これで、CommentモデルからPostモデルにアクセスし、値を取得できる

所感

  • hasManyについてはhasOneの複数系になっただけなので、わかりやすい

  • belongsToなのかhasManyなのか少し混乱するので、親子関係を意識

→個人的には実際に書き出してみてどちらのモデルが親か視覚化するとわかりやすい