【Laravel基礎】複数のテーブルの結びつけ【リレーション】

#概要#
Laravel学習で自分がつまずいた部分を備忘録としてまとめています。
今回は複数のテーブルの結びつけに関する記事です。

#この記事でわかる事#
テーブルの結合方法(リレーション)
①テーブルの主従関係
②テーブルの設定
③モデルの設定

以下、記事内容です！


##テーブルの主従関係##
今回はPostテーブルとCommentsテーブルを用意して、結合します。

こうした複数テーブルの結合を`リレーション`と呼びます。
そして、リレーションにおいて重要なのが`主従関係`です。
一方のテーブルが主テーブル・もう一方が従テーブルとなり、
この主従関係によって書くコードが変わってきます。

今回の場合だと、Post(記事)に対してComments(コメント)がつくので、
`Postテーブルが主、Commentsテーブルが従`という関係になります。
ブログのイメージですね。記事がまず先にあって、それに対してコメントがつく。
Twitterだと、まずユーザーがいて、そこから投稿が生まれる。
`それが無いと成り立たない側のテーブルが主テーブル`になります。

従テーブルは`主テーブルのIDを保管するフィールド`を用意する必要があります。
このフィールドを`外部キー`と呼びます。

これを踏まえて、テーブルを設定していきます。

##テーブルの設定##
今回はPostテーブルとCommentsテーブルを用意しました。
■Postテーブル

```laravel:posts_table.php
   public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }
```

まずは主テーブルになるPostsテーブル。
こちらは通常通りですね。ID,title,body,投稿日時を設定しました。

■Commentsテーブル
    
```laravel:comments_table.php
     public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->increments('id')          
       　　①$table->integer('post_id');　
            $table->string('body');
            $table->timestamps();
          ②$table->foreign('post_id')
                  ->references('id')
                  ->on('posts')
                  ->onDelete('cascade');
        });
    }
```

従テーブルになるCommentsテーブルですが、
従テーブルでは下記２つの設定をする必要があります。

①外部キーの作成
`主テーブルのIDを保管するためのフィールド`を作成しておきます。
今回はPostテーブルのidを保管するので、'post_id'フィールドとします。

②外部キーの参照先を設定
`記事が消された際、紐づくコメントも消されるように設定しないといけません。`
ここでは外部キーの参照先を指定し、参照先のデータが消えたら、このテーブルのデータも一緒に消えるよう指示しています。
各コードの内容は下記のような感じですね。
`//  foreign(フィールド)      = このフィールドは下記を参照します
 //  references(フィールド)   = 参照先のフィールド
 //  on(テーブル名)　　　　　  = 参照先のテーブル
 //  onDelete('cascade');  = 上記が削除されたら該当データも一緒に削除`

以上がテーブルの設定です。

##モデル##

次に、モデルの更新です。
まずは主テーブルとなるPostモデルを更新します。
■Postモデル(主)

```laravel:Post.php
    class Post extends Model
{
    protected $fillable = ['title', 'body'];

    // ①Commentモデルとの紐付け
    public function comments() {
        return $this->hasMany('App\Comment');
    }
}
```

①commentテーブルとリンクさせるためのcomments関数を作成します。
主テーブルでは、
`$this -> hasMany(参照先モデル)`とする事で
従テーブルのデータを引っ張ることが可能になります。

■Commentモデル（従）
次にCommentモデルを更新します。

```laravel:Comment.php
    class Comment extends Model
{
    //
    protected $fillable = ['body'];

    // ②Postモデルへの紐付け
    public function post() {
    return $this->belongsTo('App\Post');
    }

}
```

②Postテーブルとリンクさせるためのpost関数を作成します。
従テーブルでは、
`$this -> belingsTo(参照先モデル)`とする事で
従テーブルのデータを引っ張ることが可能になります。

belongToは所属すると言う意味なので、主テーブルに従ずると言う感じですね。


##リレーションの確認
ここまでで、テーブルが結合できたかターミナルで確認します。
まずはPostテーブル→Commentsテーブルの確認。
ここでは`(①) App\Post::find(2)->comments;`によって、
PostテーブルのID:2のデータを呼び出し、
紐づくCommentsテーブルのデータを呼び出しています。


```laravel:ターミナル

>>>
(①) App\Post::find(2)->comments;

       App\Comment {#3962
         id: "3",
         post_id: "2",
         body: "test",
         created_at: "2020-11-18 17:48:51",
         updated_at: "2020-11-18 17:48:51",
       },
     ],
   }
>>> 
```

こうですね。紐づくコメントの中身が出てきたのでOKです。

次にCommentsテーブル→Postテーブルへのリレーションを確認します。

```laravel:ターミナル
>>> App\Comment::find(3)->post;
=> App\Post {#3963
     id: "2",
     title: "title 2",
     body: "body 2",
     created_at: "2020-11-18 17:55:50",
     updated_at: "2020-11-18 17:55:50",
   }
>>> 
```
こちらも出てきたのでOKです。


##まとめ##
以上、Laravelにおけるテーブルのリレーションでした。
初めは、hasMany( )とbelongTo( )の違いがよくわからなかったのですが、
主従関係と言う概念を理解すると、違いが腹落ちしました。

最後まで読んで頂きありがとうございました！