Lors de l'exécution des migrations laravel, je suis confronté à un petit inconvénient. J'utilise Laravel 5.1.
Puisqu'il y a beaucoup de tables avec de nombreuses relations, il est probablement impossible que je renomme les fichiers de migration afin qu'ils s'exécutent dans le bon ordre, donc aucune contrainte de clé étrangère n'est violée. C'est ce que j'ai fait une fois dans le passé et c'était très peu pratique.
Ce que je fais maintenant, c'est définir chaque migration comme ceci:
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;');
}
}
Le problème avec cela est qu'il est fastidieux d'écrire et qu'il encombre le code.
J'ai également pensé à créer deux fichiers de migration factices, dont le seul but serait d'activer et de désactiver les vérifications de clés étrangères, et je les nommerais de telle manière qu'elles s'exécuteraient au début et à la fin de chaque migration.
S'il existe une solution élégante, serait-il possible de l'appliquer également au processus d'ensemencement, car cela a également tendance à être un problème.
C'est évidemment une solution très improvisée, et je demande s'il y a une meilleure façon de le faire. Existe-t-il des méthodes beforeMigrate
et afterMigrate
que je peux remplacer ou quelque chose du genre?
Et sinon, comment procédez-vous?
Toutes les idées seraient appréciées, je n'aime pas toutes les options que j'ai énoncées.
J'avais une tâche similaire à accomplir lorsque Lumen/Laravel a commencé à utiliser Passport et j'ai dû abandonner la précédente oauth mise en œuvre du serveur de lucadegasperi/oauth2 -server-laravel .
J'ai finalement réussi à faire avancer les choses en créant 2 migrations, où la première efface les clés étrangères et la seconde supprime les tables.
J'ai dû utiliser des dates avant les migrations de Laravel's Passport (2016-06-01) afin qu'elles soient exécutées avant celles-ci.
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();
}
//...
}
Et dans le deuxième fichier 2016_05_31_000001_clear_old_oauth.php
//...
public function up()
{
Schema::disableForeignKeyConstraints();
Schema::drop('oauth_access_tokens');
//...
Schema::enableForeignKeyConstraints();
}
//...
J'ai obtenu cela en extrayant la logique de la clé étrangère dans un fichier de migration distinct. Cela m'a aidé à:
Dans du code:
//file: 2017_06_19_230601_fk_postuser_table.php
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('post_user');
}
Un autre aspect important à retenir est de supprimer d'abord la clé étrangère, puis la colonne. La suppression de la colonne génère d'abord l'erreur:
Cannot drop index 'tableName_columnName_foreign': needed in a foreign key constraint
Le bon ordre est important:
public function down()
{
Schema::table('tableName', function (Blueprint $table) {
$table->dropForeign(['columnName']); // fk first
$table->dropColumn('columnName'); // then column
});
}
Parfois, la meilleure façon de procéder consiste à toujours supprimer les clés étrangères créées dans votre code de migration de restauration.
Supposons que vous ayez une clé étrangère dans votre schéma up
comme suit:
Schema::table('mytable', function (Blueprint $table) {
$table->foreign(mycolumn)->references('id')->on(foreigntable);
}
Dans votre migration down
, vous devriez avoir
$table->dropForeign(mytable_mycolumn_foreign);//this is how laravel generates the foreign keys