Laravel migraties leuke manier om buitenlandse sleutelcontroles uit te schakelen

Bij het uitvoeren van laravel-migraties heb ik te maken met een klein ongemak. Ik gebruik Laravel 5.1.

Omdat er veel tabellen zijn met veel relaties, is het waarschijnlijk onmogelijk dat ik de migratiebestanden hernoem, zodat ze in de juiste volgorde worden uitgevoerd, zodat er geen beperking van externe sleutels wordt geschonden. Dit was wat ik in het verleden eens deed, en het was erg onpraktisch.

Wat ik nu doe, is elke migratie als volgt definiëren:

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

Het probleem hiermee is dat het vervelend is om te schrijven en de code onoverzichtelijk maakt.

Ik heb er ook over nagedacht om twee dummy-migratiebestanden te maken, waarvan het enige doel zou zijn om de externe sleutelcontroles in en uit te schakelen, en ik zou ze zo noemen dat ze aan het begin en het einde van elk zouden worden uitgevoerd migratie.

Als er een elegante oplossing is, zou het dan mogelijk zijn om deze ook toe te passen op het zaaiproces, aangezien dit ook daar een probleem is.

Dit is duidelijk een zeer geïmproviseerde oplossing en ik vraag of er een betere manier is om dit te doen. Zijn er enkele beforeMigrateen afterMigratemethoden die ik kan overschrijven of iets dergelijks?

En zo niet, hoe doe je dat dan?

Alle inzichten worden op prijs gesteld, ik houd niet van alle opties die ik heb genoemd.


Antwoord 1, autoriteit 100%

Ik had een soortgelijke taak bij de hand toen Lumen / Laravel Passport begon te gebruiken en ik moest de vorige oauth-serverimplementatie verwijderen van lucadegasperi/oauth2-server-laravel.

Ik ben er eindelijk in geslaagd om dingen op gang te krijgen door 2 migraties te maken, waarbij de eerste buitenlandse sleutels wist en de tweede de tabellen daadwerkelijk verwijdert.

Ik moest datums gebruiken vóór de migraties van Laravel’s Passport(2016-06-01) dus ze zullen eerder worden uitgevoerd.

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

En in het tweede bestand
2016_05_31_000001_clear_old_oauth.php

//...
public function up()
{
    Schema::disableForeignKeyConstraints();
    Schema::drop('oauth_access_tokens');
    //...
    Schema::enableForeignKeyConstraints();
}
//...

Antwoord 2, autoriteit 4%

Ik heb dit voor elkaar gekregen door de vreemde-sleutellogica uit te pakken in een apart migratiebestand. Dit heeft me geholpen om:

  • Schakel de externe sleutelbeperkingen uit.
  • Zet de database veilig neer, als deze bestaat.

In code:

//file: 2017_06_19_230601_fk_postuser_table.php
public function down()
{
        Schema::disableForeignKeyConstraints();
        Schema::dropIfExists('post_user');
}

Antwoord 3

Een ander belangrijk aspect om te onthouden is om EERST de ForeignKey te laten vallen en daarna de kolom. Als je de kolom eerst laat vallen, krijg je de fout:

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

De juiste volgorde is belangrijk:

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

Other episodes