Laravel migrations nice way of disabling foreign key checks
Another important aspect to remember is to drop the foreignKey FIRST, then the column. Dropping the column first throws the error:
Cannot drop index 'tableName_columnName_foreign': needed in a foreign key constraint
The proper order matters:
public function down()
{
Schema::table('tableName', function (Blueprint $table) {
$table->dropForeign(['columnName']); // fk first
$table->dropColumn('columnName'); // then column
});
}
I had a similar task at hand when Lumen / Laravel started using Passport and I had to ditch the previous oauth server implementation from lucadegasperi/oauth2-server-laravel.
I finally managed to get things going by creating 2 migrations, where the first one clears foreign keys and the second one actually deletes the tables.
I had to use dates before the migrations of Laravel's Passport (2016-06-01) so they will be executed before those.
2016_05_31_000000_clear_old_oauth_relations.php
//...
class ClearOldOauthRelations extends Migration
{
public function up()
{
Schema::disableForeignKeyConstraints();
// drop foreign keys
Schema::table('oauth_access_tokens', function (BluePrint $table) {
$table->dropForeign('oauth_access_tokens_session_id_foreign');
});
//...
Schema::enableForeignKeyConstraints();
}
//...
}
And in the second file
2016_05_31_000001_clear_old_oauth.php
//...
public function up()
{
Schema::disableForeignKeyConstraints();
Schema::drop('oauth_access_tokens');
//...
Schema::enableForeignKeyConstraints();
}
//...
I got this done by extracting the foreign key logic into a separate migration file. This helped me to:
- Disable the foreign key constraints.
- Securely drop the database, if it exists.
In code:
//file: 2017_06_19_230601_fk_postuser_table.php
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('post_user');
}