Laravel migrations nice way of disabling foreign key checks
When running laravel migrations, I am facing a small inconvenience. I use Laravel 5.1.
Since there are a lot of tables with many relationships, it is probably impossible that I rename the migration files so they run in the correct order, so no foreign key constraint is violated. This was what I did once in the past, and it was very inpractical.
What I'm doing now is defining each migration like this:
class CreateSomeTable extends Migration
{
public function up()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
// my table definitions go here
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
public function down()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
// drop table
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
}
The problem with this is that it's tedious to write and it clutters up the code.
I've also thought about creating two dummy migration files, whose only purpose would be to enable and disable the foreign key checks, and I would name them in such a way that they would run at the beginning and the end of each migration.
If there is an elegant solution, would it be possible to apply it to the seeding process as well, since this tends to be a problem there as well.
This is obviously a very improvised solution, and I am asking if there is a better way of doing it. Is there some beforeMigrate
and afterMigrate
methods that I can override or something along those lines?
And if not, how do you go about doing it?
Any insights would be appreciated, I dislike all the options I have stated.
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');
}