I'm making a course on Laravel Sanctum: MasteringAuth.com

Creating laravel foreign keys

Constantin Druc · 09 Mar, 2022

This is a tiny tip for more experienced Laravel developers. Laravel developers who have been working with the framework for a long time that might have missed this small, but nice, migrations improvement.

In the past, to set a foregin key you first had to add an unsignedBigInteger with the name of the column, and then, typically at the end of the callback, you would use the blueprint foreign() method, pass it the column name, and then reference the id on the other table.

1Schema::create('events', function (Blueprint $table) {
2 $table->id();
3 $table->unsignedBigInteger('user_id');
4 $table->unsignedBigInteger('person_id');
5 $table->string('name');
6 $table->date('date');
7 $table->string('repeat_every');
8 $table->string('notify_days_before');
9 $table->timestamps();
10 
11 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
12 $table->foreign('person_id')->references('id')->on('people')->onDelete('cascade');
13});

However, in newer versions of Laravel, there is a better way to do this.

Instead of unsignedBigInteger, we can do:

1Schema::create('events', function (Blueprint $table) {
2 $table->id();
3 $table->foreignId('user_id')->constrained()->onDelete('cascade');
4 $table->foreignId('person_id')->constrained()->onDelete('cascade');
5 $table->string('name');
6 $table->date('date');
7 $table->string('repeat_every');
8 $table->string('notify_days_before');
9 $table->timestamps();
10});

Now, the constrained() method will use conventions to determine the table and column name being referenced, but if your table name somehow doesn’t match, you can pass it as argument.

1Schema::create('events', function (Blueprint $table) {
2 $table->id();
3 $table->foreignId('user_id')->constrained('users')->onDelete('cascade');
4 $table->foreignId('person_id')->constrained('people')->onDelete('cascade');
5 $table->string('name');
6 $table->date('date');
7 $table->string('repeat_every');
8 $table->string('notify_days_before');
9 $table->timestamps();
10});

That’s it.

Usually, I don’t get that excited by syntactic sugar, but this is significantly better.

Not only because it’s shorter and more expressive, but because it also makes code easier to delete - and code that’s easy to delete is always better.

This was tiny tip #2 - I hope you enjoyed it.