Laravel 迁移禁用外键检查的好方法
Laravel migrations nice way of disabling foreign key checks
当 运行ning 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;');
}
}
这样做的问题是编写起来很乏味,而且会使代码混乱。
我还考虑过创建两个虚拟迁移文件,其唯一目的是启用和禁用外键检查,我会以这样的方式命名它们 运行每次迁移的开始和结束。
如果有一个优雅的解决方案,是否也可以将其应用于播种过程,因为这也往往是一个问题。
这显然是一个非常临时的解决方案,我想问一下是否有更好的方法。是否有一些我可以覆盖的 beforeMigrate
和 afterMigrate
方法或类似的方法?
如果没有,你会怎么做?
任何见解都将不胜感激,我不喜欢我所说的所有选项。
当 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();
}
//...
我通过将外键逻辑提取到单独的迁移文件中来完成此操作。这帮助我:
- 禁用外键约束。
- 安全删除数据库(如果存在)。
在代码中:
//file: 2017_06_19_230601_fk_postuser_table.php
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('post_user');
}
要记住的另一个重要方面是先删除外键,然后再删除列。首先删除该列会引发错误:
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
});
}
当 运行ning 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;');
}
}
这样做的问题是编写起来很乏味,而且会使代码混乱。
我还考虑过创建两个虚拟迁移文件,其唯一目的是启用和禁用外键检查,我会以这样的方式命名它们 运行每次迁移的开始和结束。
如果有一个优雅的解决方案,是否也可以将其应用于播种过程,因为这也往往是一个问题。
这显然是一个非常临时的解决方案,我想问一下是否有更好的方法。是否有一些我可以覆盖的 beforeMigrate
和 afterMigrate
方法或类似的方法?
如果没有,你会怎么做?
任何见解都将不胜感激,我不喜欢我所说的所有选项。
当 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();
}
//...
我通过将外键逻辑提取到单独的迁移文件中来完成此操作。这帮助我:
- 禁用外键约束。
- 安全删除数据库(如果存在)。
在代码中:
//file: 2017_06_19_230601_fk_postuser_table.php
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('post_user');
}
要记住的另一个重要方面是先删除外键,然后再删除列。首先删除该列会引发错误:
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
});
}