Laravelの外部キー制約を指定する際に使用するconstrained()に任意の指定したidを付与する方法

公式の書き方を参照すると、外部キー制約を追加する際、マイグレーションファイルに下記を記述する

```php:マイグレーショファイル
# userテーブルと紐付ける条件で作成した
Schema::create('posts', function (Blueprint $table) {
    $table->id('post_id');
    
    $table->foreignId('user_id')->constrained('users')->onDelete('cascade');
    # または
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    
    $table->timestamps();
});
```
:::note warn
- 今回は、CASCADEの設定も行っている
- 著者は、userテーブルを題材として使用し、今回の説明を行う
:::

上記の記述の場合、userテーブルが下記の状態であれば、マイグレーションを正常に行う事ができる

|id|name|emeil|
|-------|-------|-------|
|1|test1|aaa@example.com|
|2|test2|aaa@aaa.com|

しかし、下記のテーブル構造だった場合、上記の外部キー制約の書き方では、マイグレーションが正常に動作しない
（マイグレーションを実行するとエラーとなる）

|user_id|name|emeil|
|-------|-------|-------|
|1|test1|aaa@example.com|
|2|test2|aaa@aaa.com|

エラー文は、下記が表示される
```sh
Illuminate\Database\QueryException 

SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'user_id' (SQL: alter table `posts` add constraint `posts_user_id_foreign` foreign key (`user_id`) references `user_id` (`id`) on delete cascade)

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:760
    756▕         // If an exception occurs when attempting to run a query, we'll format the error
    757▕         // message to include the bindings with SQL, which will make this exception a
    758▕         // lot more helpful to the developer instead of just the database's errors.
    759▕         catch (Exception $e) {
  ➜ 760▕             throw new QueryException(
    761▕                 $query, $this->prepareBindings($bindings), $e
    762▕             );
    763▕         }
    764▕     }

      +9 vendor frames 
  10  database/migrations/2023_01_04_231333_create_posts_table.php:22
      Illuminate\Support\Facades\Facade::__callStatic("create")

      +36 vendor frames 
  47  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
```
DBにアクセスして、エラーで表示されているSQL文を修正し、修正したクエリーを叩けば正常にDBを動かす事ができるが、それではマイグレーションファイルを使う意味がなくなってしまう。また、実際の業務での開発を想定した場合、マイグレーションが正常に動作しないのは、明らかに他の人の迷惑にも繋がる。

```sql:DBに接続して直接SQL文を打って修正を試みた為、その内容も記述する
/* エラーで出力されたSQL文 */
alter table `posts` 
add constraint `posts_user_id_foreign` 
foreign key (`user_id`) references `user_id` (`id`) on delete cascade

/* エラー文で出力されたSQLを修正したSQL文 */
alter table `posts` 
add constraint `posts_user_id_foreign` 
foreign key (`user_id`) references `user_id` (`user_id`) on delete cascade
```
SQL文を見ると `references` の `（）` に任意で指定したid名が入力できれば、正常に動作する事が分かる。
しかし、マイグレーションファイルに正常に動作するSQLを記述する方法が、公式ドキュメントを確認しても記述されていなかった。
ここで、各メソッドの裏側の処理を確認した際、`constrained（）`の裏側の処理にヒントがあった。

```php:constrained()の処理
/**
     * Create a foreign key constraint on this column referencing the "id" column of the conventionally related table.
     *
     * @param  string|null  $table
     * @param  string  $column
     * @return \Illuminate\Database\Schema\ForeignKeyDefinition
     */
    public function constrained($table = null, $column = 'id')
    {
        return $this->references($column)->on($table ?? Str::of($this->name)->beforeLast('_'.$column)->plural());
    }
```

`constrained（)`の第二引数に任意で指定したid名を入力すれば、正常に動作するのではと思い、第二引数にidを記述したら、正常にマイグレーションができるようになりました。
下記が修正したコード

```diff_php
# 修正前
- $table->foreignId('user_id')->constrained('users')->onDelete('cascade');

# 修正後
+ $table->foreignId('user_id')->constrained('users', 'user_id')->onDelete('cascade');
```
同じ問題で困っている人がいましたら、是非参考にしてみて下さい。

# 参考資料
- [LARAVEL 9.x データベースを真新しくし、データベースの初期設定を実行する](https://search.readouble.com/?query=constrained)
- [Laravelの外部キー制約でCASCADEを設定するときに使える新しいメソッド](https://qiita.com/aminevsky/items/0cd41d86f61b01ef8141)
- [Laravel8で外部キー制約を追加する](https://zenn.dev/msksgm/articles/20211105-larvale8-migrate-foreign-key)