Php Laravel迁移是禁用外键检查的好方法
在运行laravel迁移时,我面临着一个小小的不便。我使用的是Laravel5.1 由于有许多表具有许多关系,因此我可能不可能重命名迁移文件,使其以正确的顺序运行,因此不会违反外键约束。这是我过去做过的一次,非常实际 我现在要做的是如下定义每个迁移:Php Laravel迁移是禁用外键检查的好方法,php,laravel,migration,Php,Laravel,Migration,在运行laravel迁移时,我面临着一个小小的不便。我使用的是Laravel5.1 由于有许多表具有许多关系,因此我可能不可能重命名迁移文件,使其以正确的顺序运行,因此不会违反外键约束。这是我过去做过的一次,非常实际 我现在要做的是如下定义每个迁移: class CreateSomeTable extends Migration { public function up() { DB::statement('SET FOREIGN_KEY_CHECKS=0;');
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;');
}
}
这样做的问题是编写起来很乏味,而且代码也很混乱
我还考虑过创建两个虚拟迁移文件,它们的唯一用途是启用和禁用外键检查,并且我将以这样的方式命名它们,即它们将在每次迁移的开始和结束时运行
如果有一个优雅的解决方案,是否也可以将其应用于播种过程,因为这往往也是一个问题
这显然是一个非常即兴的解决方案,我想知道是否有更好的方法。是否有一些在迁移之前和迁移之后的方法可以覆盖,或者类似的方法
如果没有,你怎么做呢
任何见解都将不胜感激,我不喜欢我所说的所有选项。当Lumen/Laravel开始使用Passport时,我手头有一个类似的任务,我不得不放弃以前的oauth服务器实现
最后,我创建了两个迁移,第一个迁移清除外键,第二个迁移实际删除表
我必须使用(2016-06-01)迁移之前的日期,因此它们将在迁移之前执行
2016\u 05\u 31\u000000\u clear\u old\u oauth\u 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();
}
//...
}
//...
public function up()
{
Schema::disableForeignKeyConstraints();
Schema::drop('oauth_access_tokens');
//...
Schema::enableForeignKeyConstraints();
}
//...
在第二个文件中
2016\u 05\u 31\u000001\u clear\u old\u oauth.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();
}
//...
}
//...
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');
}
另一个需要记住的重要方面是先删除foreignKey,然后删除列。删除列首先会引发错误:
无法删除索引“tableName\u columnName\u foreign”:外键约束中需要索引
正确的顺序很重要:
public function down()
{
Schema::table('tableName', function (Blueprint $table) {
$table->dropForeign(['columnName']); // fk first
$table->dropColumn('columnName'); // then column
});
}
如果使用artisan创建迁移,并且它们具有正确的时间戳,则它们应始终以正确的顺序运行。它们按时间戳的顺序运行……是的,这就是我提到文件顺序时的意思。问题是,有时您没有按照正确的顺序生成它们,或者有时您可能存在循环依赖关系,即两个表都有相互引用的外键。无论以何种顺序运行该示例,除非禁用检查,否则都会出现外键约束冲突。避免此问题的最佳方法是先创建表,然后创建另一个创建/删除键的迁移。不特别相关,但是您也可以通过这种方式禁用外键检查:\DB::getSchemaBuilder()->disableForeignKeyConstraints()
。不确定是否有更好的方法调用此方法。我又遇到了完全相同的问题,还有另一个项目。作为一名临时黑客,我完全按照OP中的建议行事;2个时间戳为在所有其他操作之前和之后运行的虚拟迁移文件,分别关闭和打开外键检查。我相信拉威尔的移民体系存在根本缺陷。查看所有这些文件之间拆分的表创建代码既难看又不方便。从现在起,我将把所有内容都放在一个迁移文件中,在开始和结束时禁用和启用外键检查,并在它们之间清楚地列出所有模式逻辑。这真是太好了!这是最近才添加的,还是已经在laravel中添加了一段时间,但当我遇到这个问题时我没有注意到?嗨@Pavlin,我不知道这是什么时候在laravel/Lumen中添加的。请注意,您需要在例如PhpMyAdmin(结构->关系)中查找外键约束的名称,这是自5.2版以来添加到Laravel的