Database Seeding von bestehenden Tabellen

Database Seeding aus Tabellen

Nachdem ich schon einige Projekte mit dem Laravel PHP-Framework umgesetzt habe, stellte sich das folgende Problem:

  • Das Live-System ist eingerichtet
  • Das Integrations-System ist eingerichtet
  • Der Source-Code liegt auf dem Integrations-System
  • Die Datenbank ist bereit mit Standardwerten bzw. anderen statischen Informationen befüllt

…wie bekommt man nun diese Informationen, welche bereits in der Datenbank vorhanden sind auf das Live-System wobei:

  1. Die Informationen ebenfalls in der Code-Versionierung wie zum Beispiel SVN oder GIT mitprotokolliert werden
  2. Die Daten mit in das „Setup“ des Laravel Projektes aufgenommen werden ohne zusätzliche Routinen zu erstellen
  3. Kein manueller Code zusammengestellt werden muss, welcher die Daten per Skript und/oder MySQL-Statements in die Datenbank bringt
  4. Die bestehenden Daten aus dem Integrationssystem verwendet werden können

Die Lösung für die Punkte 1 bis 3 ist schnell gefunden: Database Seeding

Database Seeding

Dazu bietet Laravel bereits eine sehr gute Möglichkeit die bestehende Datenbank mit Testdatensätze zu befüllen. Dieser Prozess kann aber ebenfalls dafür verwendet werden, bestimmte Tabellen mit vordefinierten Werten zu befüllen. Vielleicht wird hierbei das Database Seeding etwas zweckentfremdet, aber das Vorgehen führt zu gewünschten Effekt. Laravel bietet bereits eine gute Anleitung für die Basics zum Erstellen von Database Seeds.

Um die einfachste Art von Database Seeding kurz vorzustellen nun einen kurzen Crashkurs.

Neue Seeder erstellen

Der Speicherort für die Seeds findet man unter app/database/seeds. Dort befindet sich die Datei DatabaseSeeder.php. Diese Datei stellt die Ausgangsbasis für die Seeding-Aktivitäten dar. Um nun einen neuen „Seeder“ zu erstellen kann man entweder direkt in der DatabaseSeeder.php eine neue Klasse für den Seeder anlegen oder diese in eine eigene Datei auslagern. Im folgenden stelle ich kurz die zweite Variante vor. Dazu erstellt man im Ordner app/database/seeds eine neue PHP-Datei mit dem Namen „TestSeeder.php“ in diese Datei wird nun folgender Code gelegt:

<?php

class TestSeeder extends Seeder {
    public function run(){
        //Hier kommt der Code um die Datenbank zu befüllen
        //z.B. ein Objekt erstellen
        MyTestObject::create(array(
            'Attribut' => 'Wert'
        ));
    }
}

Wichtig sind hierbei zwei Dinge: Erstens muss die gerade erstellte Klasse von der Klasse „Seeder“ erben. Zweitens muss der Einsprungspunkt, die Methode run() vorhanden sein. Anschließen müssen wir den Database Seeder nur noch mitteilen, dass wir einen neuen Seeder erstell haben und dieser ausgeführt werden soll. Dazu erweitert man die Datei DatabaseSeeder.php unter app/database/seeds wie folgt:

class DatabaseSeeder extends Seeder {

    public function run()
    {
        //Dieser Aufruf führt die run() Methode aus
        $this->call('TestSeeder');
        //Feedback, dass Seed durchgeführt wurde (optional)
        $this->command->info('MyObject table seeded!');
    }

}

Seeder ausführen

Nachdem die Datei gespeichert wurde kann man per Konsole mit folgenden Aufruf den Seeder, oder wenn man mehrere Seeder erstellt hat, alle gemeinsam ausführen und damit die Datenbank mit den benötigten Daten befüllen.

//Führt alle Seeder aus
php artisan db:seed
//Führt nur den TestSeeder aus
php artisan db:seed --class=TestSeeder

Diese Aufrufe ermöglichen es alle oder nur einzelne Seeder auszuführen um eine oder mehrere Tabellen mit Daten zu befüllen. Diesen Vorgang nennt man Database Seeding.

Database Seeding aus bestehenden Tabellen

Durch diese Vorgehensweise hätte man die Probleme 1 bis 3 gelöst. Was ist aber, wenn man bereits Daten in den Tabellen hat? Dafür gibt es nun ein geniales Tool, welches uns einen Seeder aus bereits bestehenden Tabellen und Daten erstellt. Dieses Tool ist iseed und liegt für uns bereit bei GitHub.

Installation

Die Installation erfolgt mittels Composer, nachdem wir das Packet in unsere composer.json unter den benötigten Packeten eingetragen haben und mittels Konsolenaufruf in unserem Projektordner

composer update

ausgeführt haben. Damit das Packet nun intern verwendet werden kann muss man nur noch den Service Provider unter app/config/app.php eintragen. Genaueres zur Installation findet sich auf der iseed GitHub Seite.

Inverse Database Seeding

Der Aufruf des Packetes bzw. der Funktionalität gestaltet sich so einfach wie die Installation. Entweder man ruft die Funktionalität in seinem Code (Controller oder Model) per Iseed::generateSeed('table_name'), wobei table_name den Tabellennamen darstell, auf. Mir persönlich gefällt der Aufruf per Konsole aber besser, da für mein Problem nur ein einfacher Abzug der bestehenden Daten notwendig ist. Dazu führt man folgenden Befehl in der Konsole aus:

php artisan iseed table_name

Auch hier steht table_name wieder für den entsprechenden Tabellennamen. Nach der Ausführung passieren zwei Dinge:
1. Eine neue Seeder-Klasse wird für uns under app/database/seeds erstellt und mit allen benötigten Daten befüllt
2. Der Aufruf der neuen Seeder-Klasse wird im File DatabaseSeeder.php direkt hinzugefügt.
Danach steht nichts mehr im Wege den erstellten Seeder in einer neuen Instanz der Laravel-Web-App einzusetzen.

Database Seeding

Wir können nun in der neuen Instanz per Datenbank-Migration die für unsere Klassen benötigten Tabellen anlegen lassen (vorrausgesetzt die Datenbank-Verbindung ist bereits korrekt eingestellt ;-)). Dies geschiet mittels dem Konsolenaufruf:

php artisan migrate

Dadurch werden alle Datenbank-Adaptionen die wir zuvor erstellt habe durchgeführt. Wenn wir nun die Tabellen mit den zuvor erstellten Seeder befüllen wollen erfolgt das mittels:

php artisan db:seed

Und Voilà, die Daten aus der Tabelle sind nun in der neuen Instanz verfügbar. Wird der Sourcecode auch noch mittels SVN oder einer anderen Technik versioniert, können so die Informationen auch in die Versionierung mitaufgenommen werden. Ich hoffe diese Tool sowie das inverse Database Seeding biete auf so auch so viel Komfort wie mir.