There is one change in Laravel 5.8 that is not mentioned in the official Upgrade Guide but caused me problems - I couldn't create a foreign key migration, and spent half-hour until found out the reasons. So I want to share, maybe you will encounter the same thing.
My Situation Example and Error
While working on one project, I've created a simple table transaction_types:
php artisan make:migration create_transaction_types_table
And added just one new string() field:
Schema::create('transactions_types', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
And then tried to create a migration for transactions table with a foreign key, with same syntax I used to do all the time:
php artisan make:migration create_transactions_table
Migration file content:
Schema::create('transactions', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('transaction_type_id')->unsigned();
$table->foreign('transaction_type_id')->references('id')->on('transactions_types');
$table->decimal('amount');
$table->timestamps();
});
And here's what happened when running php artisan migrate:
As usual, the error "cannot add foreign key constraint" doesn't give much details so I was just guessing, what could go wrong:
- Typo in table name? Double-checked, nope.
- Too long foreign key name? (should be up to 64 characters) Doesn't seem so.
- Mismatch in foreign key field types? Hmmm, then I noticed something...
Look closer at what Laravel is generating when doing php artisan make:migration command:
Schema::create('transactions_types', function (Blueprint $table) {
$table->bigIncrements('id');
// ...
bigIncrements. BIG increments. And then, of course, if you're doing a foreign key from just "unsigned integer" type (as I always did my whole life), it fails. Type mismatch. Obviously.
How to Fix
Well, it's easy. There are two ways to make it work:
- Either change original migration from bigIncrements() to just increments();
- Or in your foreign key column do bigInteger() instead of integer().
The choice is yours.
Why Am I so Angry About It
Simple - this change wasn't mentioned anywhere in 5.8 changes.
- Official 5.8 Upgrade guide? Nope. Well, ok, it doesn't affect the project during upgrade specifically, so maybe it's fair.
- Laravel News official blog: main announcement by Paul Redmond? Not a word.
- Same blog: maybe one of the articles about 5.8? Nothing there either.
So, it makes me think that probably it's only me with this problem, and everyone else will actually notice that migrations are being generated with bigIncrements().
After some googling, I've found one Reddit thread and one Stackoverflow post about it. That's it.
Oh, and, of course, it was mentioned and discussed in the official Github repository of Laravel, back in November 2018:
- [Laravel Ideas Proposal] Switch the default increments() to a bigint #1384
- Commit to stub: use bigIncrements
- Discussion after someone got same error as me: SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint #27717
Don't get me wrong, I'm not against that change to bigIncrements(). I'm just angry about how it was (NOT) communicated. Probably only a bunch of people participating in internal Github communications actually knew about this change.
P.S. Oh, by the way, default users table migration also comes with bigIncrements():
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
So whenever you create new fields with foreign key to users, don't forget to use bigInteger().
No comments or questions yet...