【Laravel】foreignIdはどのように参照されるか

Laravel

【テーブル】
Booksテーブル
Categoriesテーブル

upメソッドでforeignIdが使われていたとする。

以下の記述はBooksテーブルを作成するものだ。

$table->foreignId('category_id')->constrained();であるが、これはどうやらCategoriesテーブルのidを参照するらしい。

public function up(): void
    {
        Schema::create('books', function (Blueprint $table) {
            $table->id();
            $table->string('title', 100);
            $table->foreignId('category_id')->constrained();
            $table->timestamps();
        });
    }

この仕組みがよくわからなかったので調べてみた。

foreignIdメソッドとの解説

foreignId

foreignIdメソッドは、外部キー(foreign key)を定義するために使われます。

このコードでは、category_idというカラムを作成しています。このカラムは通常、関連する別のテーブル(ここではcategories)のIDを参照します。

デフォルトでは、作成されるカラムの型は BIGINT UNSIGNED となります。

外部キー(Foreign Key)とは?
外部キーとは、データベースにおける”リレーション(関係)”を表現するために使われる特別なキーです。
あるテーブルの列が、”他のテーブルの主キー(Primary Key)”を参照している場合、その列を外部キーと呼びます。

constrained

constrainedメソッドは、foreignIdで作成したカラムに外部キー制約(foreign key constraint)を設定します。

このメソッドを使うと、以下を自動的に行います。

外部キー制約を作成します。

外部キーの参照先テーブルを推測します(カラム名のプレフィックスから)。

例: category_idcategoriesテーブルのidカラムを参照します。

onDelete(‘cascade’)のような動作を追加できます(デフォルトでは設定されませんが、必要に応じて後述のように拡張可能です)。


ここから本題に入ります。

参照先として自動的に推測されること

参照先のテーブル名

$table->foreignId('category_id')->constrained();

category_idのcategory部分をもとに、categoriesテーブルが推測されます。

デフォルトの動作(名前から推測)

  • 推測される参照先テーブル名:categories
  • 参照先カラム名:id

->constrained()を使う場合、デフォルトの挙動として外部キーの名前(例: category_id)のプレフィックス部分(category)をもとに、参照先テーブル名が自動的に推測されます。このため、カラム名とテーブル名の命名規則が一致させるのが自然だし、便利に使える。

さらにこの仕組みを知っていればLaravelを使用している人ならば”予測ができる”という意味でわかりやすさに繋がる。

参照先のカラム名

外部キーが参照するカラム名はデフォルトでidが選ばれます。

カスタマイズ

外部キーが参照するカラムは何もしなければidが選ばれるということがわかった。

では参照するテーブルやカラムを指定することはできるのか?

→できる

参照先のテーブル名やカラム名を明示的に指定したい場合

外部キーがデフォルトのテーブル・カラムを参照しない場合は、以下のように明示的に指定できます。

$table->foreignId('category_id')->constrained('custom_table_name', 'custom_column_name');

外部キーの挙動を制御(onDeleteなど)

onDeleteonUpdateを使って外部キーの動作を制御できます。

$table->foreignId('category_id')->constrained()->onDelete('cascade');

onDelete(‘cascade’)

categoriesテーブルの参照するレコードが削除された際、自動的にこのテーブルの関連レコードも削除します。

onDelete(‘restrict’)

参照先レコードが削除されるのを防ぎます。

まとめ

  • $table->foreignId('category_id')->constrained();ならcategory_idのプレフィックス:categoryからcategoriesテーブルを参照する。
  • デフォルトでIDを参照する。(カスタマイズ可能)

categoriesテーブルに関連付けられた外部キー制約を持つcategory_idカラムを作成する。

自動で外部キー制約を設定することで、参照整合性(referential integrity)を保つ仕組みをデータベースに組み込むことができる。