web-dev-qa-db-fra.com

Remplir une base de données dans un fichier de migration Laravel

J'apprends seulement Laravel et j'ai un fichier de migration qui crée un tableau d'utilisateurs. J'essaie de renseigner un enregistrement d'utilisateur dans le cadre de la migration:

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

    });
}

Mais je reçois le message d'erreur suivant lors de l'exécution de php artisan migrate:

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

Ceci est évidemment dû au fait qu'Artisan n'a pas encore créé la table, mais toute la documentation semble indiquer qu'il existe un moyen d'utiliser Fluent Query pour renseigner des données dans le cadre d'une migration.

Quelqu'un sait comment? Merci!

75
Adam Hopkinson

Ne placez pas DB :: insert () dans Schema :: create (), car la méthode create doit finir de créer la table avant de pouvoir insérer des éléments. Essayez ceci à la place:

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

Je sais que ceci est un ancien post, mais comme il est mentionné dans une recherche google, je pensais partager quelques connaissances ici. @ erin-geyer a souligné que le fait de mélanger des migrations et des sources de données peut créer des problèmes, et @justamartin a répondu que parfois vous souhaitiez/souhaitiez que les données soient renseignées dans le cadre de votre déploiement.

J'irais un peu plus loin et dirais qu'il est parfois souhaitable de pouvoir appliquer les modifications de données de manière cohérente afin de pouvoir, par exemple, effectuer un déploiement dans la mise en scène, voir que tout va bien, puis passer à la production avec l'assurance des mêmes résultats (et ne pas avoir à se souvenir de courir une étape manuelle).

Cependant, il est toujours utile de séparer la semence et la migration car ce sont deux préoccupations liées mais distinctes. Notre équipe a fait des compromis en créant des migrations qui appellent des semoirs. Cela ressemble à:

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

Cela vous permet d'exécuter une graine une fois, tout comme une migration. Vous pouvez également implémenter une logique qui empêche ou augmente le comportement. Par exemple:

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

Ceci exécuterait évidemment votre semoir de manière conditionnelle s'il y a moins de 10 SomeModels. Ceci est utile si vous souhaitez inclure le segment comme un segment standard exécuté lorsque vous appelez artisan db:seed et lors de la migration afin de ne pas "doubler". Vous pouvez également créer un segment inverse pour que les restaurations fonctionnent comme prévu, par exemple.

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

Le deuxième paramètre --force est requis pour permettre au segmenteur de fonctionner dans un environnement de production.

63
darrylkuhn

Voici une très bonne explication de la raison pour laquelle utiliser Database Seeder de Laravel est préférable à Migrations: http://laravelbook.com/laravel-database-seeding/

Bien que suivre les instructions de la documentation officielle soit une bien meilleure idée car la mise en œuvre décrite sur le lien ci-dessus ne semble pas fonctionner et est incomplète. http://laravel.com/docs/migrations#database-seeding

10
Erin Geyer

Cela devrait faire ce que vous voulez.

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

Une autre façon simple de le faire est de définir une méthode privée qui crée une instance et conserve le modèle concerné.

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

Avec cette solution, les champs d'horodatage seront générés par Eloquent.

EDIT: Il est préférable d’utiliser le système de division pour distinguer la génération de la structure de la base de données et la population de la base de données.

0
Maximilien DI DIO

J'ai essayé cette méthode d'insertion de base de données, mais comme elle n'utilise pas le modèle, elle a ignoré un trait sluggable que j'avais sur le modèle. Donc, étant donné que le modèle pour cette table existe, dès que sa migration a été effectuée, j'ai pensé que le modèle serait disponible pour l'insertion de données. Et je suis venu avec ceci:

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

Cela a fonctionné correctement et a également pris en compte le trait sluggable sur mon modèle pour générer automatiquement un slug pour cette entrée et utilise également les horodatages. NB L'ajout de l'identifiant n'était pas nécessaire, cependant, je voulais des identifiants spécifiques pour mes catégories dans cet exemple. Testé en travaillant sur Laravel 5.8

0
Andrew Arscott