webentwicklung-frage-antwort-db.com.de

Laravel : Migrationen und Seeding für Produktionsdaten

Meine Anwendung benötigt einen vorab registrierten Datensatz, um zu funktionieren. Ich muss sie also in die Datenbank einfügen, wenn ich die Anwendung eingerichtet habe.

Laravel schlägt zwei Mechanismen vor:

  • Datenbankmigrationen : "Sie ermöglichen einem Team, das Datenbankschema zu ändern und über den aktuellen Schemazustand auf dem Laufenden zu bleiben."
  • Database Seeding : "Laravel bietet auch eine einfache Möglichkeit, Ihre Datenbank mithilfe von Seed-Klassen mit Testdaten zu samen."

Wenn ich diese Beschreibung lese, scheint keine dieser Lösungen angepasst zu sein.

Eine ähnliche Frage war gefragt zu stackoverflow und beantwortet . In der Antwort wird vorgeschlagen, die Datenbank durch Auffüllen der Datenbank durch Auffinden der aktuellen Umgebung aufzufüllen:

<?php

class DatabaseSeeder extends Seeder {

    public function run()
    {
            Eloquent::unguard();

            if (App::environment() === 'production')
            {
                $this->call('ProductionSeeder');
            }
            else
            {
                $this->call('StagingSeeder');
            }
    }

}

Diese Lösung funktioniert natürlich. Ich bin mir jedoch nicht sicher, ob dies der richtige Weg ist, denn durch das Einfügen von Daten mithilfe von Setzern verlieren Sie alle Vorteile, die der Migrationsmechanismus bietet (Datenbank-Upgrade, Rollback ...).

Ich möchte wissen, was in diesem Fall die beste Vorgehensweise ist.

34
gontard

Bei der Entwicklung von Laravel geht es um Freiheit. Wenn Sie also Ihre Produktionsdatenbank säen müssen und denken, dass DatabaseSeeder der beste Ort dafür ist, warum nicht?

Okay, Sämaschine soll hauptsächlich mit Testdaten verwendet werden, aber Sie werden einige Leute sehen, die sie so verwenden, wie Sie sind.

Ich sehe diese wichtige Art von Start als Teil meiner Migration, da dies nicht in meinen Datenbanktabellen enthalten sein kann und artisan migrate jedes Mal ausgeführt wird, wenn ich eine neue Version meiner Anwendung bereitstelle 

php artisan migrate:make seed_models_table

Und mache mein Seedind-Zeug darin:

public function up()
{
    $models = array(
        array('name' => '...'),
    );

    DB::table('models')->insert($models);
}

Ich habe mich oft gefragt, was die richtige Antwort darauf ist. Persönlich würde ich vermeiden, Seeding zu verwenden, um die erforderlichen Zeilen in der Datenbank aufzufüllen, da Sie eine Menge bedingter Logik hinzufügen müssen, um sicherzustellen, dass Sie nicht versuchen, etwas zu füllen, das bereits vorhanden ist. (Das Löschen und Wiederherstellen der Daten ist sehr nicht empfehlenswert, da Sie mit den Schlüsselfehlern konfrontiert werden könnten. Wenn Sie kaskadierende Löschvorgänge verwenden, können Sie versehentlich eine Last Ihrer Datenbank abwischen. Mein Fehler! ;-)

Ich füge das "Seeding" von Zeilen in das Migrationsskript ein. Die Chancen stehen gut, dass die Daten als Teil des Rollouts vorhanden sein müssen.

Es ist erwähnenswert, dass Sie die DB-Klasse anstelle von Eloquent-Modellen verwenden sollten, um diese Daten aufzufüllen, da sich Ihre Klassenstruktur im Laufe der Zeit ändern könnte, was Sie daran hindern wird, die Datenbank von Grund auf neu zu erstellen (ohne den Verlauf neu zu schreiben und Ihre Migrationsdateien zu ändern.) Ich bin mir sicher, dass es eine schlechte Sache ist.)

Ich würde dazu neigen, mit so etwas zu gehen:

public function up()
{
    DB::beginTransaction();

    Schema::create(
        'town',
        function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        }
    );

    DB::table('town')
        ->insert(
            array(
                array('London'),
                array('Paris'),
                array('New York')
            )
        );

    Schema::create(
        'location',
        function (Blueprint $table) {
            $table->increments('id');
            $table->integer('town_id')->unsigned()->index();
            $table->float('lat');
            $table->float('long');
            $table->timestamps();

            $table->foreign('town_id')->references('id')->on('town')->onDelete('cascade');
        }
    );

    DB::commit();
}

Dies erlaubt mir dann, den Stadttisch leicht zu "säen", wenn ich ihn zum ersten Mal erstellt habe, und ich werde mich nicht mit irgendwelchen Ergänzungen stören, die zur Laufzeit gemacht wurden.

28
Dan B

Das ist was ich in der Produktion verwende.

Da ich bei jeder Bereitstellung eine Migration durchführe

artisan migrate

Ich erstelle einen Seeder (nur um das Aussondern von Daten aus der Migration für einen späteren Zugriff zu verhindern und um zu wissen, welche Daten ich gesichtet habe, indem ich nur Dateien im Seeder-Verzeichnis schaue)

php artisan make:seeder YourTableSeeder

und nennen Sie es dann in einer Migration.

class YourTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {    
        $seeder = new YourTableSeeder();
        $seeder->run();
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
    }
}

Ich füge diesen Seed-Aufruf nicht zu seeds/DatabaseSeeder.php hinzu, um zu vermeiden, dass er bei einer neuen Installation zweimal ausgeführt wird.

1
Manpreet