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

问题描述 投票:20回答:4

在进行laravel迁移时,我面临一些小小的不便。我使用Laravel 5.1。

由于存在许多具有许多关系的表,因此我可能无法重命名迁移文件,因此它们以正确的顺序运行,因此不会违反外键约束。这就是我过去做过的事情,而且非常不实用。

我现在正在做的是定义每个迁移,如下所示:

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

这样做的问题在于它编写起来很繁琐,并且使代码变得混乱。

我还考虑过创建两个虚拟迁移文件,其唯一目的是启用和禁用外键检查,我会以这样的方式命名它们,它们将在每次迁移的开始和结束时运行。

如果有一个优雅的解决方案,也可以将它应用于播种过程,因为这也是一个问题。

这显然是一个非常即兴的解决方案,我想问是否有更好的方法。是否有一些beforeMigrateafterMigrate方法,我可以覆盖或沿着这些线?

如果没有,你怎么去做呢?

任何见解都会受到赞赏,我不喜欢我所说的所有选项。

php laravel migration
4个回答
27
投票

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

我终于设法通过创建2个迁移来实现目标,其中第一个清除外键,第二个实际删除表。

我必须在Laravel's Passport(2016-06-01)的迁移之前使用日期,所以它们将在那之前执行。

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

3
投票

我通过将外键逻辑提取到单独的迁移文件中来完成此操作。这帮助我:

  • 禁用外键约束。
  • 安全地删除数据库(如果存在)。

在代码中:

//file: 2017_06_19_230601_fk_postuser_table.php

public function down()
{
        Schema::disableForeignKeyConstraints();
        Schema::dropIfExists('post_user');
}

0
投票

要记住的另一个重要方面是删除foreignKey FIRST,然后删除列。首先删除列会引发错误:

Cannot drop index 'tableName_columnName_foreign': needed in a foreign key constraint

正确的顺序很重要:

    public function down()
    {
        Schema::table('tableName', function (Blueprint $table) {
            $table->dropForeign(['columnName']); // fk first

            $table->dropColumn('columnName'); // then column
        });
    }

0
投票

有时,最好的方法是始终在回滚迁移代码中删除创建的外键。

假设您的up架构中有一个外键,如下所示:

Schema::table('mytable', function (Blueprint $table) {
    $table->foreign(mycolumn)->references('id')->on(foreigntable);
}

在你的down迁移中,你应该有

$table->dropForeign(mytable_mycolumn_foreign);//this is how laravel generates the foreign keys
© www.soinside.com 2019 - 2024. All rights reserved.