In Laravel, migrations are a way to modify and manage the database schema of the application. A foreign key is a field that is used to establish the relationship between two tables via the primary key (You can also use a non-primary field but not recommended).
In this tutorial, I show how you can add a foreign key constraint while creating a table using migration in the Laravel 10 project.

Table of Content
1. Database Configuration
Open .env file.
Specify the host, database name, username, and password.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=tutorial DB_USERNAME=root DB_PASSWORD=
2. Create Table and add Foreign Key Using Migration
Create countries, states, and cities tables using migration.
I am adding foreign key on states and cities tables.
statestable is linked tocountriestable, andcitiestable is linked tostatestable.
Countries Table
- Create
Countriestable –
php artisan make:migration create_countries_table
- Now, navigate to
database/migrations/folder from the project root. - Find a PHP file that ends with
create_countries_tableand open it. - Define the table structure in the
up()method.
public function up()
{
Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
States Table
- Create
Statestable –
php artisan make:migration create_states_table
- Similarly, find a PHP file that ends with
create_states_tableindatabase/migrations/folder and open it. - Define the table structure in the
up()method.
Adding foreign key –
- I am adding a foreign key to
country_idfield. - Set datatype of this field to UNSIGNED BIGINT –
$table->unsignedBigInteger('country_id');. Datatype must beUNSIGNEDand same as the parent table linking field datatype. - Here,
countriestableidfield hasbigintegerdatatype. - Add foreign key –
$table->foreign('country_id')
->references('id')->on('countries')->onDelete('cascade');
Values –
- foreign() – Pass field name which you want to foreign key constraint.
- references() – Pass linking table field name.
- on() – Linking table name.
- onDelete(‘cascade’) – Enable deletion of attached data.
public function up()
{
Schema::create('states', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('country_id');
$table->string('name');
$table->timestamps();
$table->foreign('country_id')
->references('id')->on('countries')->onDelete('cascade');
});
}
Cities Table
- Create
Citiestable –
php artisan make:migration create_cities_table
- Similarly, find a PHP file that ends with
create_cities_tableindatabase/migrations/folder and open it. - Define the table structure in the
up()method.
Adding foreign key –
- I am adding a foreign key to
states_idfield. - Set datatype of this field to UNSIGNED BIGINT –
$table->unsignedBigInteger('state_id');. Datatype must beUNSIGNEDand same as the parent table linking field datatype. - Here,
statestableidfield hasbigintegerdatatype. - Add foreign key –
$table->foreign('state_id')
->references('id')->on('states')->onDelete('cascade');
Values –
- foreign() – Pass field name which you want to foreign key constraint.
- references() – Pass linking table field name.
- on() – Linking table name.
- onDelete(‘cascade’) – Enable deletion of attached data.
public function up()
{
Schema::create('cities', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('state_id');
$table->string('name');
$table->foreign('state_id')
->references('id')->on('states')->onDelete('cascade');
$table->timestamps();
});
}
- Run the migration to create tables –
php artisan migrate
3. Create Models
Create Countries, States, and Cities models.
Countries Model
- Create
CountriesModel.
php artisan make:model Countries
- Open
app/Models/Countries.phpfile. - Specify mass assignable Model attributes –
nameusing the$fillableproperty.
Completed Code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Countries extends Model
{
use HasFactory;
protected $fillable = [
'name'
];
}
States Model
- Create
StatesModel.
php artisan make:model States
- Open
app/Models/States.phpfile. - Specify mass assignable Model attributes –
country_id, andnameusing the$fillableproperty.
Completed Code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class States extends Model
{
use HasFactory;
protected $fillable = [
'country_id','name'
];
}
Cities Model
- Create
CitiesModel.
php artisan make:model Cities
- Open
app/Models/Cities.phpfile. - Specify mass assignable Model attributes –
state_id, andnameusing the$fillableproperty.
Completed Code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Cities extends Model
{
use HasFactory;
protected $fillable = [
'state_id','name'
];
}
4. Conclusion
Adding a foreign key to the table using migration in Laravel is a straightforward process. By following these steps, you can easily define a foreign key constraint and maintain referential integrity between tables in your database.
In the example, I added a single foreign key to a table but you can add more than one foreign key to a table by following the same steps.
Follow the same steps if you are on Laravel 9 or 8.
View this official document to know more about foreign key implementation.
If you found this tutorial helpful then don't forget to share.
Thanks for sharing. In addition to your content, ensure that both tables have same database engine. My project is over 9 years old so my database engine was MyISAM and Innodb. It took me several hours to figure out what the problem was.