🥐

Laravelで外部キーが複数ある場合のリレーション Composhipsを使って多対多のデータを取得する方法

に公開

はじめに

LaravelのEloquentは、リレーションを簡単に扱うことができます。しかし、外部キーが複数あるリレーションになると、Laravelの標準機能では使うことができません。

そんなときに便利なのが、Composhipsというパッケージです。
本記事では、Composhipsを使って多対多の外部キーが複数あるリレーションをどのように実装するかを紹介します。

複合キー(Composite Key)とは?

複合キーとは、複数のカラムを組み合わせて1つのキー(主キーや外部キー)として扱う設計のことです。
例えば、「user_id と store_id の両方が一致するデータを紐づけたい」といったケースで使われます。

LaravelのEloquentでは、通常1つのキーを使ってリレーションを定義しますが、複合キーのように2つ以上のカラムをキーにする場合、標準のリレーション定義では対応できません。
そのため、複合キーに対応したリレーションを使いたい場合は、Composhipsのような外部パッケージを導入する必要があります。

Composhipsが必要なケース

LaravelのbelongsTo, hasMany, belongsToManyなどのリレーションは、通常は単一キーで結びつけます。しかし、以下のようなケースでは、複合キーが必要になります。

例えば、user_idとcompany_idを組み合わせてリレーションを張るようなケースです

users

Column Description
id ユーザーID(PK)
company_id 所属会社ID(FK)

projects

Column Description
id プロジェクトID(PK)
company_id 所属会社ID(FK)

project_user

Column Description
user_id ユーザーID(users.id への FK)
project_id プロジェクトID(projects.id への FK)
company_id 所属会社ID(users / projects どちらにも対応可能)

リレーション説明

  • usersprojects は多対多の関係
    • 中間テーブル project_user を通じて関連付け
  • users.company_id = projects.company_id(同じ会社内のユーザーとプロジェクトが紐づく)
  • project_useruser_idproject_id の複合キーで構成

このような構造では、単一キーでは意図しないデータが結びついてしまうため、複合キーでのマッチングが必要です。

導入手順

Composhipsのインストール
まずは、パッケージをインストールします。

composer require topclaudy/compoships

インストール後は、特別な設定は不要で、リレーション定義に使うだけです。

モデルの準備
Composhipsを使いたいモデルにTraitを追加します。

use Awobaz\Compoships\Compoships;

class User extends Model
{
    use Compoships;

    public function projects()
    {
        return $this->belongsToMany(Project::class, 'project_user', ['user_id', 'company_id'], ['project_id', 'company_id']);
    }
}

同様に、ProjectモデルにもComposhipsを記載します。

use Awobaz\Compoships\Compoships;

class Project extends Model
{
    use Compoships;

    public function users()
    {
        return $this->belongsToMany(User::class, 'project_user', ['project_id', 'company_id'], ['user_id', 'company_id']);
    }
}

データ取得例
上記のリレーション定義ができれば、あとは通常のリレーションと同じように使えます。

$projects = User::find(1)->projects;

foreach ($projects as $project) {
    echo $project->name;
}

内部的には、user_idとcompany_idの両方を使ってproject_userテーブルを結合してくれます。

まとめ

LaravelのEloquentは標準では複合キーに非対応となっています。

ただ、Composhipsを使うことで複合キーでのリレーションが可能になります。

複合キーの設計は一見面倒に感じるかもしれませんが、Composhipsを導入すればLaravelでも扱えるようになります。
複雑なリレーションが必要なプロジェクトでは、ぜひ一度導入を検討してみてください!

株式会社アクトビ

Discussion