Переходы Laravel - отличный способ отключения проверки внешнего ключа
При выполнении миграций 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
, которые я могу переопределить или что-то в этом роде?
И если нет, как вы это делаете?
Любые идеи будут оценены, мне не нравятся все варианты, о которых я говорил.
Ответы
Ответ 1
У меня была аналогичная задача, когда Lumen/Laravel начал использовать Passport, и мне пришлось отказаться от предыдущей реализации oauth-сервера из lucadegasperi/oauth2-server-laravel.
Наконец-то мне удалось добиться успеха, создав 2 миграции, где первая очищает внешние ключи, а вторая фактически удаляет таблицы.
Мне нужно было использовать даты перед миграциями Laravel 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();
}
//...
Ответ 2
Я сделал это, извлекая логику внешнего ключа в отдельный файл миграции. Это помогло мне:
- Отключить ограничения внешнего ключа.
- Безопасное удаление базы данных, если она существует.
В коде:
//file: 2017_06_19_230601_fk_postuser_table.php
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('post_user');
}
Ответ 3
Еще один важный аспект, который следует помнить, - это опустить 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
});
}
Ответ 4
Иногда лучший способ это сделать - всегда добавлять созданные внешние ключи в код переноса отката.
Допустим, у вас есть внешний ключ в вашей схеме 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