wake-up-neo.net

Füllen einer Datenbank in einer Laravel-Migrationsdatei

Ich lerne gerade Laravel und habe eine funktionierende Migrationsdatei, die eine Benutzertabelle erstellt. Ich versuche, einen Benutzerdatensatz als Teil der Migration auszufüllen:

public function up()
{
    Schema::create('users', function($table){

        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();

        DB::table('users')->insert(
            array(
                'email' => '[email protected]',
                'verified' => true
            )
        );

    });
}

Beim Ausführen von php artisan migrate wird jedoch die folgende Fehlermeldung angezeigt:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'vantage.users' doesn't exist

Dies liegt natürlich daran, dass Artisan die Tabelle noch nicht erstellt hat, aber die gesamte Dokumentation scheint zu sagen, dass es eine Möglichkeit gibt, Fluent Query zu verwenden, um Daten als Teil einer Migration aufzufüllen.

Weiß jemand wie? Vielen Dank!

75
Adam Hopkinson

Fügen Sie DB :: insert () nicht in Schema :: create () ein, da die create-Methode die Erstellung der Tabelle beenden muss, bevor Sie etwas einfügen können. Versuchen Sie es stattdessen:

public function up()
{
    // Create the table
    Schema::create('users', function($table){
        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();
    });

    // Insert some stuff
    DB::table('users')->insert(
        array(
            'email' => '[email protected]',
            'verified' => true
        )
    );
}
161
BenjaminRH

Ich weiß, dass dies ein alter Beitrag ist, aber da er bei einer Google-Suche auftaucht, dachte ich, ich würde etwas Wissen hier teilen. @ erin-geyer wies darauf hin, dass das Mischen von Migrationen und Setzern Kopfschmerzen verursachen kann, und @justamartin widerspricht, dass manchmal Daten als Teil Ihrer Bereitstellung aufgefüllt werden sollen/müssen.

Ich würde noch einen Schritt weiter gehen und sagen, dass es manchmal wünschenswert ist, Datenänderungen konsistent ausrollen zu können, so dass Sie zum Beispiel Staging bereitstellen, sehen können, dass alles in Ordnung ist, und dann mit der Überzeugung der gleichen Ergebnisse für die Produktion bereitstellen (und muss nicht daran denken, einen manuellen Schritt auszuführen).

Es ist jedoch immer noch sinnvoll, das Saatgut und die Migration voneinander zu trennen, da dies zwei verwandte, aber unterschiedliche Anliegen sind. Unser Team hat einen Kompromiss eingegangen, indem es Migrationen geschaffen hat, die Setzer anrufen. Das sieht so aus:

public function up()
{
    Artisan::call( 'db:seed', [
        '--class' => 'SomeSeeder',
        '--force' => true ]
    );
}

Auf diese Weise können Sie einen Seed wie bei einer Migration einmal ausführen. Sie können auch eine Logik implementieren, die Verhalten verhindert oder verbessert. Zum Beispiel:

public function up()
{
    if ( SomeModel::count() < 10 )
    {
        Artisan::call( 'db:seed', [
            '--class' => 'SomeSeeder',
            '--force' => true ]
        );
    }
}

Dies würde natürlich Ihren Seeder bedingt ausführen, wenn weniger als 10 SomeModels vorhanden sind. Dies ist nützlich, wenn Sie die Sämaschine als Standardsämaschine verwenden möchten, die ausgeführt wird, wenn Sie artisan db:seed aufrufen, sowie bei der Migration, damit Sie nicht "verdoppeln". Sie können auch eine Rückwärtssämaschine erstellen, damit die Rollbacks wie erwartet funktionieren, z.

public function down()
{
    Artisan::call( 'db:seed', [
        '--class' => 'ReverseSomeSeeder',
        '--force' => true ]
    );
}

Der zweite Parameter --force ist erforderlich, damit die Sämaschine in einer Produktionsumgebung ausgeführt werden kann.

63
darrylkuhn

Hier ist eine sehr gute Erklärung dafür, warum die Verwendung von Laravel Database Seeder der Verwendung von Migrationen vorzuziehen ist: http://laravelbook.com/laravel-database-seeding/

Das Befolgen der Anweisungen in der offiziellen Dokumentation ist jedoch eine viel bessere Idee, da die unter dem obigen Link beschriebene Implementierung nicht zu funktionieren scheint und unvollständig ist. http://laravel.com/docs/migrations#database-seeding

10
Erin Geyer

Dies sollte tun, was Sie wollen.

public function up()
{
    DB::table('user')->insert(array('username'=>'dude', 'password'=>'z19pers!'));
}
3
strings28

Eine weitere saubere Methode ist die Definition einer privaten Methode, die das betreffende Modell instanziert und persistiert.

public function up()
{
    Schema::create('roles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('label', 256);
        $table->timestamps();
        $table->softDeletes();
    });

    $this->postCreate('admin', 'user');
}

private function postCreate(string ...$roles)  {
    foreach ($roles as $role) {
        $model = new Role();
        $model->setAttribute('label', $role);
        $model->save();
    }
}

Bei dieser Lösung werden Zeitstempelfelder von Eloquent generiert.

BEARBEITEN: Es ist besser, das Seeder-System zu verwenden, um die Generierung der Datenbankstruktur und die Datenbankbelegung zu deaktivieren.

0

Ich habe diese DB-Einfügemethode ausprobiert, aber da sie das Modell nicht verwendet, hat sie eine fehlerhafte Eigenschaft ignoriert, die ich für das Modell hatte. Angesichts der Tatsache, dass das Modell für diese Tabelle vorhanden ist, stellte ich fest, dass das Modell zum Einfügen von Daten zur Verfügung stehen würde, sobald es migriert wurde. Und ich habe mir das ausgedacht:

public function up() {
        Schema::create('parent_categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
        ParentCategory::create(
            [
                'id' => 1,
                'name' => 'Occasions',
            ],
        );
    }

Dies funktionierte ordnungsgemäß und berücksichtigte auch die Eigenschaft sluggable in meinem Modell, automatisch einen Slug für diesen Eintrag zu generieren, und verwendet auch die Zeitstempel. NB. Das Hinzufügen der ID war nicht erforderlich. In diesem Beispiel wollte ich jedoch bestimmte IDs für meine Kategorien. Getestet mit Laravel 5.8

0
Andrew Arscott