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 どちらにも対応可能) |
リレーション説明
-
users
とprojects
は多対多の関係- 中間テーブル
project_user
を通じて関連付け
- 中間テーブル
-
users.company_id
=projects.company_id
(同じ会社内のユーザーとプロジェクトが紐づく) -
project_user
はuser_id
とproject_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