Join my Alpine.js course on Udemy for free 👀

Foreign Id to same table in Laravel migrations

April 29, 2022  ‐ 2 min read

Creating foreign Id's in Laravel abstracts away quite a lot if you adhere to the naming conventions. That is; when you're about to add a foreign Id called user_id, Laravel assumes from the Id name you want to reference the id from the users table.

Setting up such a relation to the same table is an option too, but it requires you to overwrite this default behavior. See the following, where a foreign Id is created called parent_id. If we would Laravel try to figure out which table this should reference then it would try to create a foreign key constrained to a table called parents.

<?php
...
$table->foreignId('parent_id')->constrained()->onDelete('cascade');
...

Instead, you want to specify the table name your are referencing as the first argument to the constrained() method:

<?php
...
$table->foreignId('parent_id')->constrained('pages')->onDelete('cascade');
...

Such a pattern is useful when you have models that have somewhat of a recursive structure; a directory model that has a parent directory for example.

See for a full migration the example below:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('pages', function (Blueprint $table) {
            $table->id();
            $table->foreignId('parent_id')->constrained('pages')->onDelete('cascade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('pages');
    }
};