端くれプログラマの備忘録 Laravel [Laravel] has Many Through Relationsの使いどころ

[Laravel] has Many Through Relationsの使いどころ

LaravelのEloquentにおける「hasManyThrough」リレーションは、「中間テーブル」を経由して別のテーブルに関連付けられたレコードを取得するための関係を表します。2つのテーブルをつなぐ中間テーブルを経由して、多対多のような関係を簡単に操作できます。

具体的な例を用いて説明します。

例: 国 -> ユーザー -> 投稿

考えられる3つのテーブルがあります:

  1. countries(国)
  2. users(ユーザー)
  3. posts(投稿)

各テーブルは次のように関連付けられています:

  • 1つの国は複数のユーザーを持つことができる(hasMany関係)。
  • 1人のユーザーは複数の投稿を持つことができる(hasMany関係)。

この場合、国から直接投稿を取得するためにhasManyThroughを使用できます。つまり、国を起点として、ユーザーを経由して投稿にアクセスします。

実装例

// Countryモデル
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(
            Post::class,  // 最終的に取得したいモデル
            User::class,  // 中間モデル
            'country_id', // 中間モデルの外部キー (usersテーブルに存在する)
            'user_id',    // 最終的なモデルの外部キー (postsテーブルに存在する)
            'id',         // ローカルキー (countriesテーブルの主キー)
            'id'          // 中間テーブルのローカルキー (usersテーブルの主キー)
        );
    }
}

引数の説明

  • 第一引数:最終的に関連付けられているモデル名 (Post::class)
  • 第二引数:中間モデル名 (User::class)
  • 第三引数:中間モデル (usersテーブル) が参照する外部キー (country_id)
  • 第四引数:最終的なモデル (postsテーブル) が参照する外部キー (user_id)
  • 第五引数:ローカルキー (デフォルトは id)
  • 第六引数:中間モデルのローカルキー (デフォルトは id)

使用例

Countryモデルのインスタンスから、関連するすべての投稿を取得できます。

$country = Country::find(1);
$posts = $country->posts; // この国に関連するすべての投稿を取得

このように、hasManyThroughを使うと、中間テーブルを経由して簡単にリレーションを設定し、データを取得できます。