LaravelのbelongsToManyで中間テーブルの情報を取得する

今回扱うテーマはデータ間の多対多の関係で2つのテーブルをつなぐ中間データが持つ情報も取得したいということを考えます。
まず、講師一覧を表すteacherというテーブルがあります。とりあえず、idとnameを持つとします。
id    name
1    鈴木
2    佐藤
3    田中
4    山田
次に、教える科目を表すsubjectというテーブルがあります。こちらも簡単に考えるため、idとsubject_nameのみを持っているとします。
id    subject_name
1    英語
2    数学
3    国語
4    社会
5    理科
さらに、講師は複数の科目を担当できるものとします。ただし、メインで教える科目とサブで教える科目は区別します。
そして、teacherとsubjectを結ぶteacher_subjectというテーブルがあります。これはteacher_id、subject_idに加えてメイン、サブを区別するtypeというカラムがあります(メインなら1、サブなら2)。
teacher_id    subject_id    type
1                  1                1
1                  4                2
2                  2                1
2                  5                2
3                  3                1
4                  4                1
4                  3                2
ここで、こんな表を作りたいとします。
講師    科目    種類
鈴木 英語 メイン
鈴木 社会 サブ
佐藤 数学 メイン
佐藤 理科 サブ
田中 国語 メイン
山田 社会 メイン
山田 国語 サブ

このとき、モデルクラスTeacher.php, Subject.phpに加えてTeacherSubject.phpをそれぞれ以下の様に用意します。

app\Teacher.php

<?php 
namespace App;
use Illluminate\Database\Eloquent\Model;

class Teacher extends Model
{
    protected $fillable = [
        'name'
    ];
    protected $table = "teacher";

    public function subjects()
    {
        return $this->belongsToMany('App\Subject', 'teacher_subject', 'teacher_id', 'subject_id')
            ->using('App\TeacherSubject')
            ->withPivot('type');
    }
}

app\Subject.php

<?php
namespace App;
use Illluminate\Database\Eloquent\Model;

class Subject extends Model
{
    protected $fillable = [
        'subject_name'
    ];
    protected $table = "subject";

    public function teachers()
    {
        return $this->belongsToMany('App\Subject', 'teacher_subject', 'subject_id', 'teacher_id')
            ->using('App\TeacherSubject')
            ->withPivot('type');
    }
}

app\TeacherSubject.php

<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;

class TeacherCountry extends Pivot
{
    protected $table = "teacher_subject";
}

こんな感じでwithPivotを使うことで中間テーブルの情報を取得することができます。中間テーブルのモデルクラスはIlluminate\Database\Eloquent\Relations\Pivotを継承して作ります。

また、ある講師に対してメインの科目だけ欲しい場合は

    public function main_subjects()
    {
        return $this->belongsToMany('App\Subject', 'teacher_subject', 'teacher_id', 'subject_id')
            ->using('App\TeacherSubject')
            ->wherePivot('type', 1);
    }

という風にwherePivotで絞り込むことができます。

Eloquentのリレーションは結構奥が深いので、是非ともしっかりとマスターしたいですね。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です