web-dev-qa-db-fra.com

Laravel : Migrations et ensemencement pour les données de production

Mon application nécessite un ensemble de données pré-enregistré pour fonctionner. J'ai donc besoin de les insérer dans la base de données lors de la configuration de l'application.

Laravel propose deux mécanismes:

Quand je lis cette description, aucune de ces solutions ne semble être adaptée.

Une question similaire a été posée sur stackoverflow et avec réponse . La réponse propose d'utiliser le segment de base de données pour renseigner la base de données en détectant l'environnement actuel:

<?php

class DatabaseSeeder extends Seeder {

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

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

}

Bien sûr, cette solution fonctionne. Mais je ne suis pas sûr que ce soit la bonne façon de le faire, car en insérant des données à l'aide de semences, vous perdez tous les avantages offerts par le mécanisme de migration (mise à niveau de la base de données, restauration ...).

Je veux savoir quelle est la meilleure pratique dans ce cas.

34
gontard

Le développement de Laravel concerne la liberté. Donc, si vous avez besoin d'amorcer votre base de données de production et pensez que DatabaseSeeder est le meilleur endroit pour le faire, pourquoi pas?

D'accord, le semoir doit principalement être utilisé avec des données de test, mais vous verrez que certaines personnes l'utilisent tel quel.

Je considère ce type de graine important comme faisant partie de ma migration, car il s’agit de quelque chose qui ne peut pas être exclu de mes tables de base de données et artisan migrate est exécuté à chaque fois que je déploie une nouvelle version de mon application. 

php artisan migrate:make seed_models_table

Et créer mes trucs seedind dedans:

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

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

Je me suis souvent demandé quelle était la bonne réponse à cette question. Personnellement, j’éviterais l’utilisation de l’amorçage pour renseigner les lignes requises dans la base de données, car vous devrez mettre une charge de logique conditionnelle pour vous assurer que vous ne tentez pas de renseigner quelque chose qui existe déjà. (Supprimer et recréer les données est très déconseillé, car vous risquez de vous retrouver avec des erreurs de concordance et si vous utilisez des suppressions en cascade, vous risquez d'effacer accidentellement un chargement de votre base de données! ;-)

Je mets le "classement" des lignes dans le script de migration, car il est probable que les données devront y figurer dans le cadre du processus de déploiement.

Il convient de noter que vous devez utiliser la classe de base de données plutôt que les modèles Eloquent pour renseigner ces données, car la structure de votre classe peut changer au fil du temps, ce qui vous empêchera de recréer la base de données à partir de rien (sans réécrire l'historique ni modifier les fichiers de migration, qui Je suis sûr que c'est une mauvaise chose.)

J'aurais tendance à aller avec quelque chose comme ça:

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

Cela me permet ensuite de "semer" facilement la table de la ville lors de la création initiale et de ne pas interférer avec les ajouts qui y sont apportés au moment de l'exécution.

28
Dan B

C'est ce que j'utilise en production.

Depuis que je lance la migration sur chaque déploiement

artisan migrate

Je crée un serveur de stockage (pour que le stockage des données ne soit plus en dehors de la migration pour un accès facile plus tard, et que je sache quelles données j'ai semé en regardant simplement les fichiers dans le répertoire du serveur),

php artisan make:seeder YourTableSeeder

puis appelez-le dans une 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()
    {
    }
}

Je n'ajoute pas cet appel de départ à seed/DatabaseSeeder.php pour éviter de l'exécuter deux fois lors d'une nouvelle installation.

1
Manpreet