LoginSignup
7
13

More than 3 years have passed since last update.

同一テーブル内でのリレーションの書き方

Posted at

やること

同じテーブル内でのリレーション?なるものを実装したので備忘録

環境

  • Laravel5.8
  • Docker
  • MySQL 8.0

内部リレーションとは

あるテーブルのあるカラムの親となるカラムが同じテーブルに存在する時のこと。
例としてTwitterのようなアプリで女子高生たちが会話していると考えます。

バカ:今からスゴイこと言ってイイ?
  ↪️オタ:いいから早く言え
  ↪️バカ:諦めたらそこで試合終了じゃね?
  ↪️ロボ:すごいと思う。すでに試合終了してるのにそのセリフに感動できるあたり。

↪️はリプだと考えてください。

この情報を管理するためにはusersテーブルとcommentsテーブルが必要です。そこでそれぞれを以下のように設計します。

usersテーブル

id name
1 バカ
2 オタ
3 ロボ

commentsテーブル

id user_id comment parent_id
1 1 今からスゴイこと言ってイイ? null
2 2 いいから早く言え 1
3 1 諦めたらそこで試合終了じゃね? 1
4 3 すごいと思う。すでに試合終了してるのにそのセリフに感動できるあたり。 1

どのコメントにコメントをしたのかを表すのがparent_id です。

リレーションはこんな感じで書きます。

Comment.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    protected $guarded = ['id'];

     public function parentComment()
    {
        return $this->hasOne(Comment::class, 'id', 'parent_id');
    }
}

parentComment()は子カラムの親カラムを探す、というメソッドになっていて、第一引数に参照するモデル(テーブル)、第二引数には外部キー、第三引数には子カラムのリレーションキーを書きます。

これでどのコメントにコメントしたかをリレーションで表現できるようになります!

最後に

以前記事にしたClosureTableをEagerloadしたいときに、もし1つ上の親だけを取ってくるならこの方法で呼び出しできるようになります。
ClosureTableを使って〇〇年のアニメを季節ごとに1テーブルで管理する
今回の場合、EagerLoadするなら

Comment::with('comment.parentComment')->get()

でとることができます!

(with使っても複数リレーションするとクエリが亀になってしまうけど。。。)

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