【Laravel】リレーションとは:モデルのリレーションについて

時計 2023.10.06 / 時計

【Laravel】リレーションとは:モデルのリレーションについて

記事ではLaravelにおける、モデルのリレーションについて詳しく解説していきます。

リレーションとは複数のテーブルを関連付けることを意味します。テーブル同士をリレーションすることで、リレーション先のテーブルからデータを簡単に取得することができます。

アプリケーション開発では複数のテーブルが関連しあって動作します。リレーションはLaravelでのアプリケーション開発で必須の知識です。本記事を通して、モデルのリレーションについて理解を深めてください。

ここではLaravel10を使用しています。

テーブルのリレーションとは

アプリケーションを開発する際に、単一のテーブルのみで動くアプリケーションは稀です。基本的には複数のテーブルが関連しあい、複数のテーブルを組み合わせて1つのアプリケーションを開発します。

テーブル同士を関連付けすることで、効率的に希望のレコードを取得でき、不必要なデータベースのアクセスを削減できます。このように複数のテーブルを関連付けることをリレーションと呼びます。

例えばツイートアプリケーションではusersテーブルとtweetsテーブルを用意します。ツイートは1人のユーザーが何度でもツイートできるものとします。アプリケーションでは特定のユーザーが行ったツイートのみを表示するような仕組みが必要になります。このような場合、テーブル同士がリレーションしていることで、UserのIDからそのユーザーが行ったツイートのレコードをTweetsテーブルから簡単に取得することができます。

POINT

リレーションを利用してテーブル同士が関連しあうことで、アプリケーションの仕組みを簡単に実装できるようになります

Laravelでリレーションを設定する方法

Laravelには「Eloquent(エロクアント)」というORMが備わっており、モデル同士を紐づけることによって自動で関連するデータの取得をサポートします。

Eloquentではテーブル同士の関連付け(リレーション)を簡単にかつシンプルに扱えます。無駄なデータベースアクセスを減らすだけでなく、可読性の高いコードを書くことができます。

Laravelではテーブル同士のリレーションはモデルに記述します。

Laravel用語の確認

モデルとはMVCモデルのM(Model)にあたり、データベースとアプリケーションの架け橋となる機能です。アプリケーションでデータベース操作(取得・追加・変更・削除)を行うためにモデルは利用されます

つまりモデルにリレーションを記述してテーブル同士を関連付けることで、関連したテーブルのレコードを簡単に取得することができるということです。

2つのテーブルの関係

テーブル同士を関連付けるには「テーブルの関係」を考える必要があります。モデルでテーブルのリレーションを書く際に、テーブルの関係によって使用するメソッドが異なります。

テーブルの関係は以下の通りです。

テーブルの関係 説明
has One 2つのテーブルが1対1の関係。親テーブル側に関連付けを設定する。親テーブルから子テーブルのデータを取得するための設定
has Many 2つのテーブルが1対多の関係。親テーブル側に関連付けを設定する。親テーブルから子テーブルのデータを取得するための設定
belongs To 子テーブル側に関連付けを設定する。子テーブルから親テーブルのデータを取得するための設定

親テーブルと子テーブルとは

関係のある2つのテーブルでは外部キーと呼ばれる関連するテーブルのIDを保管するフィールドがあります。例えばArticleテーブルとCategoryテーブルを考えると、ArticleテーブルにはCategoryテーブルと関連するためのcategory_idというフィールドを用意します。

このような場合、これらのテーブルはhas Manyの関係であり、参照先(紐づけされる側)であるCategoryテーブルが親テーブル、外部キーを定義するArticleテーブルが子テーブルとなります

2つのテーブルを関連付けるにはモデル内に以下構文に沿ってコードを記述します。

構文

public function メソッド名()
{
return $this->テーブルの関係(リレーションモデル名::class);
}

モデルの関連付けに関しては次項の設定例を参考にしてください。

モデルでリレーションの設定例

ここではatrticlesテーブルとcategoriesテーブルを使ってどのように関連付け(リレーション)を行うのか簡単に解説します。

articlesテーブルとcategoriesテーブルはそれぞれ次のようにマイグレーションファイルを作成しています。

// articlesテーブルのマイグレーションファイル
public function up(): void
{
    Schema::create('articles', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->longText('body');
$table->integer('flag');
        $table->foreignId('category_id')->constrained();
        $table->timestamps();
    });
}
// categoriesテーブルのマイグレーションファイル
public function up(): void
{
    Schema::create('categories', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
}

次にこれらテーブル同士を関連付けます。以下ではCategoryモデルからArticleモデルに関連付けを行っています。

// app/Models/Category.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    public function article()
    {
        return $this->hasMany(Article::class);
    }
}

Categoryテーブルは親テーブルなので、hasManyメソッドを使っています。これにより親テーブルのレコードから、関連する子テーブルのすべてのレコードを取り出すことができます。

またフィールドflagが1のレコードだけを取得したい場合は、where句を以下のように追加します。

public function article()
{
    return $this->hasMany(Article::class)->where('flag', '=', 1);
}

次に以下ではArticleモデルからCategoryモデルに関連付けを行っています。

// app/Models/Article.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Tweet extends Model
{
    use HasFactory;

    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}

Articleテーブルは子テーブルなので、belongsToメソッドを使って子テーブルから親テーブルのレコードを取り出すことができるようにしています。

このようにモデルに関連付けを付け加えることで、モデル同士で関連するモデルのデータを取得できるようになります。