Laravel 迁移禁用外键检查的好方法

2022-01-23 00:00:00 migration php laravel

在运行 laravel 迁移时,我遇到了一点不便.我使用 Laravel 5.1.

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.

这显然是一个非常即兴的解决方案,我想问是否有更好的方法来做到这一点.是否有一些我可以覆盖的 beforeMigrateafterMigrate 方法或类似的方法?

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.

推荐答案

当 Lumen/Laravel 开始使用 Passport 时,我手头有一个类似的任务,我不得不从 lucadegasperi/oauth2-server-laravel.

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.

我终于设法通过创建 2 个迁移来让事情顺利进行,其中第一个清除外键,第二个实际删除表.

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.

我必须使用迁移 Laravel's Passport (2016-06-01) 之前的日期所以他们会在那些之前被执行.

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();
    }
    //...
}

在第二个文件中2016_05_31_000001_clear_old_oauth.php

//...
public function up()
{
    Schema::disableForeignKeyConstraints();
    Schema::drop('oauth_access_tokens');
    //...
    Schema::enableForeignKeyConstraints();
}
//...

相关文章