When creating the foreign key migrations in Laravel, a short syntax is constrained()
. With that, it's easy to make one mistake related to Column modifiers.
If you want that foreign key column to be nullable, which syntax is correct?
// Option A:$table->foreignId('user_id')->nullable()->constrained(); // Or, Option B:$table->foreignId('user_id')->constrained()->nullable();
Perhaps, you would say both?
Wrong.
On the official documentation page for the foreign keys, you may find this important sentence:
Any additional column modifiers must be called before the constrained
method.
Yes, nullable()
is one of the so-called column modifiers. So yeah, the correct way is nullable
before constrained
.
But wait, what happens if we put it the other way around?
Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->string('name'); $table->foreignId('user_id')->constrained()->nullable(); //INCORRECT! $table->timestamps();});
Would it throw an error? Not quite.
In fact, the migration will actually succeed.
That's what makes this mistake so dangerous: you may not even notice it.
You will have an issue only when saving the data:
Task::create(['name' => 'Testing']); // Will throw this:Illuminate\Database\QueryException with message 'SQLSTATE[HY000]:General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into `tasks` (`name`, `updated_at`, `created_at`) values (Testing, 2022-10-05 11:48:05, 2022-10-05 11:48:05))'
So, be careful and don't forget to add nullable
before constrained
.
In fact, it's also applicable to any other column modifiers. A few typical examples:
-
->after('name')->constrained();
and not->constrained()->after('name');
-
->default(1)->constrained();
and not->constrained()->default(1);
-
->comment('Some comment')->constrained();
and not->constrained()->comment('Some comment');
is there a way can solve this? like using phpstan?
Why does this error happen? Is the field not nullable anymore, or is the change more subtle?
Had this issue. Kept on bringing errors when running migrations. Thanks alot.