Laravel 8以降は foreignIdFor() を使う

Laravel 8で foreignIdFor() メソッドが導入されました。
外部キーカラムの定義がよりシンプルで安全になる機能です。

foreignIdFor() とは

foreignIdFor() は、モデルクラスから外部キーカラムを自動生成するメソッドです。

Before: 従来の書き方

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')
    ->references('id')
    ->on('users')
    ->onDelete('cascade');

After: foreignIdFor() を使った書き方

$table->foreignIdFor(User::class)
    ->constrained()
    ->onDelete('cascade');

わずか1行で、カラムの作成から外部キー制約の設定まで完結します。

constrained() メソッドについて

constrained() は外部キー制約を自動的に設定するメソッドです。

$table->foreignIdFor(User::class)->constrained();

このコードは以下を自動的に行います:
– モデルクラスから参照先のテーブル名を推測(Userusers
– 主キーカラム id への参照を作成
– 外部キー制約を設定

constrained() を呼ばなければ、カラムのみが作成され、外部キー制約は設定されません。

// カラムのみ作成(制約なし)
$table->foreignIdFor(User::class);

// カラム + インデックスのみ(制約なし)
$table->foreignIdFor(User::class)->index();

主なメリット

1. 型の安全性が向上

参照先のテーブルの主キー型と自動的に一致します。
users.idbigInteger なら、外部キーも unsignedBigInteger として作成されます。

2. タイプミスを防止

// モデルクラスから自動生成されるため、タイプミスが起きない
$table->foreignIdFor(User::class); // → user_id

// 従来の方法だとタイプミスのリスク
$table->unsignedBigInteger('usr_id'); // うっかりミス

3. コードの意図が明確

一目で「これは User モデルへの外部キーだ」と分かります。

注意点

モデルクラスが必要

当然ですが、モデルクラスが存在しないと使えません。

// モデルがない外部サービスのテーブルなど
$table->unsignedBigInteger('external_service_id');

カスタムテーブル名に注意

モデル名とテーブル名が規則通りでない場合は、明示的に指定が必要です。

class Person extends Model {
    protected $table = 'users';
}

// persons テーブルを探してしまうため、明示的に指定
$table->foreignIdFor(Person::class)->constrained('users');

カラム名のカスタマイズ

デフォルトでは {model}_id という名前になります。
カスタマイズする場合は第2引数を使います。

$table->foreignIdFor(User::class, 'author_id')->constrained('users');

複合主キーには非対応

複合主キーへの参照には従来の方法を使う必要があります。

よく使うパターン

// nullable な外部キー
$table->foreignIdFor(User::class)->nullable()->constrained();

// カスケード削除
$table->foreignIdFor(User::class)
    ->constrained()
    ->onDelete('cascade');

// SET NULL
$table->foreignIdFor(User::class)
    ->nullable()
    ->constrained()
    ->onDelete('set null');

// インデックスのみ(外部キー制約なし)
$table->foreignIdFor(User::class)->index();

まとめ

foreignIdFor() は、外部キー定義をより安全で保守しやすくする優れた機能です。
特別な理由がない限り、Laravel 8以降のプロジェクトでは積極的に使用することをお勧めします。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください