The two migration examples you provided are functionally similar but have some differences in how they define foreign keys and handle the down method. Let's break down the differences:
First Migration
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('contracts', function (Blueprint $table) {
$table->id();
$table->foreignId('contract_id')->constrained('contracts')->onDelete('cascade');
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::create('contracts', function (Blueprint $table) {
$table->dropForeign('contract_id_foreign');
$table->dropForeign('user_id_foreign');
});
Schema::dropIfExists('contracts');
}
};
Second Migration
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('contracts', function (Blueprint $table) {
$table->id();
$table->bigInteger('contract_id')->unsigned()->index();
$table->foreign('contract_id')->references('id')->on('contracts')->onDelete('cascade');
$table->bigInteger('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::create('contracts', function (Blueprint $table) {
$table->dropForeign('contracts_contract_id_foreign');
$table->dropForeign('contracts_user_id_foreign');
});
Schema::dropIfExists('contracts');
}
};
Key Differences
-
Foreign Key Definition:
-
First Migration: Uses
foreignIdwithconstrainedmethod, which is a more concise and modern way to define foreign keys in Laravel. -
Second Migration: Uses
bigIntegerwithforeignmethod, which is a more verbose way to define foreign keys.
-
First Migration: Uses
-
Indexing:
-
First Migration: Automatically indexes the foreign keys when using
foreignId. -
Second Migration: Explicitly adds an index using
index()method.
-
First Migration: Automatically indexes the foreign keys when using
-
Redundant Foreign Key Definition:
-
Second Migration: Has a redundant foreign key definition for
user_id. It first defines it usingbigIntegerand then again usingforeignId. This is unnecessary and should be removed.
-
Second Migration: Has a redundant foreign key definition for
-
Dropping Foreign Keys in
downMethod:-
First Migration: Uses
dropForeignwith the foreign key column names. -
Second Migration: Uses
dropForeignwith the full foreign key constraint names, which is more precise but requires knowing the exact constraint names.
-
First Migration: Uses
Recommended Approach
The first migration is more concise and follows modern Laravel conventions. Here is a cleaned-up version of the first migration:
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('contracts', function (Blueprint $table) {
$table->id();
$table->foreignId('contract_id')->constrained('contracts')->onDelete('cascade');
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('contracts', function (Blueprint $table) {
$table->dropForeign(['contract_id']);
$table->dropForeign(['user_id']);
});
Schema::dropIfExists('contracts');
}
};
This version is clean, concise, and follows best practices for defining and dropping foreign keys in Laravel migrations.