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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34298639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 23:53:56  来源:igfitidea点击:

Laravel migrations nice way of disabling foreign key checks

phplaravelmigration

提问by Pavlin

When running laravel migrations, I am facing a small inconvenience. I use Laravel 5.1.

在运行 laravel 迁移时,我遇到了一些不便。我使用 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 beforeMigrateand afterMigratemethods that I can override or something along those lines?

这显然是一个非常临时的解决方案,我在问是否有更好的方法。有一些beforeMigrateafterMigrate方法,我可以重写或类似的规定?

And if not, how do you go about doing it?

如果没有,你将如何去做?

Any insights would be appreciated, I dislike all the options I have stated.

任何见解将不胜感激,我不喜欢我所说的所有选项。

回答by 4levels

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.

当 Lumen / Laravel 开始使用 Passport 时,我手头有一个类似的任务,我不得不从lucadegasperi/oauth2-server-laravel 中放弃之前的 oauth 服务器实现。

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.

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

I had to use dates before the migrations of Laravel's Passport(2016-06-01) so they will be executed before those.

我必须在Laravel 的 Passport(2016-06-01)迁移之前使用日期,因此它们将在这些日期之前执行。

2016_05_31_000000_clear_old_oauth_relations.php

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

在第二个文件中 2016_05_31_000001_clear_old_oauth.php

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

回答by Recep Can

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');
}

回答by cmeza

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

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
        });
    }