はじめに
LaravelのEloquent ORMでは、hasMany
や belongsTo
を使ってテーブル同士の親子関係(リレーション)を定義できます。
その際によく「外部キー制約が必要なのでは?」と思われがちですが、実は Eloquentは外部キー制約がなくてもリレーションが機能します。
今回はその仕組みと注意点を、自分の備忘録としてまとめます。
①外部キー制約なしでもリレーションは使える!
Eloquentの hasMany()
や belongsTo()
は、あくまで 「モデル同士の紐付けルール(クエリの構築ルール)」 を定義しているだけです。
そのため、実際にデータベースに外部キー制約(FOREIGN KEY)がなくても機能します。
②具体例:User と Post のリレーション
posts テーブル(外部キー制約なし)
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->unsignedBigInteger('user_id'); // 外部キー制約は付けない
$table->timestamps();
});
モデル側の定義
// User.php
public function posts()
{
return $this->hasMany(Post::class);
}
// Post.php
public function user()
{
return $this->belongsTo(User::class);
}
このように定義しておけば、外部キー制約がなくても、$user->postsや$post->userは,
正しく機能します。
③なぜ動くのか?
Eloquentはリレーション定義をもとに、内部でSQLクエリを組み立てています。
例えば:
$post->user
は、実際には以下のようなクエリが実行されます:
select * form users where id = $post->user_id limit 1;
つまり、「user_idというカラムがある」ことが重要であって、DBに外部キー制約があるかどうかは関係ないということです。
④外部キー制約がなくてもよいのか?
結論から言うと、開発や学習環境ではOK!ですが、
本番環境では注意が必要です!
制約なしのメリット:
- 柔軟に開発できる
- 移行や変更が簡単(特にプロトタイプ段階)
制約なしのデメリット
- 調合性が保証されない(存在しないpost_idをpostsに設定できてしまう)
- 誤削除・参照エラーのリスク(ユーザー削除後にpostsが「孤立」することも)
⑤外部キー制約はつけるべき?
本番環境では以下のように、外部キー制約をつけることが推奨されます:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
- データの整合性を保つ
- Laravelのリレーションに加えて、DBレベルでも保証される
⑥まとめ
Laravelでは、リレーション=モデルの関係定義、外部キー制約=DBの安全ネット という意識で使い分けると理解しやすくなります!