Tutorial

Comment utiliser les bases de données Migrations et Seeders pour la configuration de la base de données abrégée dans Laravel

PHPPHP FrameworksDatabasesLaravel

Migrations et Seeders sont de puissants utilitaires de base de données fournis par le cadre PHP de Laravel pour permettre aux développeurs d'amorcer, de détruire et de recréer rapidement la base de données d'une application. Ces utilitaires aident à minimiser les problèmes d'incohérence de la base de données qui peuvent survenir lorsque plusieurs développeurs travaillent sur la même application : les nouveaux contributeurs n'ont qu'à exécuter quelques commandes artisan pour configurer la base de données lors d'une nouvelle installation.

Dans ce guide, nous allons créer des migrations et des seeders pour alimenter la base de données d'une application de démonstration de Laravel avec des exemples de données. À la fin, vous pourrez détruire et recréer les tables de votre base de données autant de fois que vous le souhaitez, en utilisant uniquement des commandes artisan.

Conditions préalables

Pour suivre ce guide, vous aurez besoin :

Remarque : dans ce guide, nous utiliserons un environnement de développement conteneurisé géré par Docker Compose pour exécuter l'application, mais vous pouvez également opter pour la mise en oeuvre de l'application sur un serveur LEMP. Pour le configurer, vous pouvez suivre notre guide sur Comment installer et configurer Laravel avec LEMP sur Ubuntu 18.04.

Étape 1 - Obtenez l'application de démonstration

Pour commencer, nous irons chercher l'application de démonstration Laravel dans son répertoire GitHub. Nous sommes intéressés par la branche tutoriel-02, qui comprend une configuration Docker Compose pour exécuter l'application sur les conteneurs. Dans cet exemple, nous allons télécharger l'application dans notre dossier d'accueil, mais vous pouvez utiliser n'importe quel répertoire de votre choix :

  • cd ~
  • curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

Parce que nous avons téléchargé le code d'application au format .zip, nous aurons besoin de la commande unzip pour le décompresser. Si vous ne l'avez pas fait récemment, mettez à jour l'index de package local de votre machine :

  • sudo apt update

Ensuite, installez le package unzip :

  • sudo apt install unzip

Puis, décompressez le contenu de l'application :

  • unzip travellist.zip

Renommez ensuite le répertoire décompressé en travellist-demo pour un accès plus facile :

  • mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

Au cours de la prochaine étape, nous allons créer un fichier de configuration .env pour configurer l'application.

Étape 2 - Configurez le fichier .env de l'application

Dans Laravel, un fichier .env est utilisé pour mettre en place des configurations dépendantes de l'environnement, telles que les références et toute information qui pourrait varier d'un déploiement à l'autre. Ce fichier n'est pas inclus dans la gestion des versions.

Attention : le fichier de configuration de l'environnement contient des informations sensibles sur votre serveur, notamment les informations d'identification de la base de données et les clés de sécurité. Par conséquent, ne partagez jamais ce fichier en public.

Les valeurs contenues dans le fichier .env auront la priorité sur les valeurs fixées dans les fichiers de configuration habituels situés dans le répertoire config. Chaque installation sur un nouvel environnement nécessite un fichier d'environnement personnalisé pour définir des éléments tels que les paramètres de connexion à la base de données, les options de débogage, et l'URL de l'application, entre autres, qui peuvent varier en fonction de l'environnement dans lequel l'application est exécutée.

Naviguez vers le répertoire travellist-demo :

  • cd travellist-demo

Nous allons maintenant créer un nouveau fichier .env afin de personnaliser les options de configuration pour l'environnement de développement que nous configurons. Laravel contient un exemple de fichier .env que nous pouvons copier pour créer le nôtre :

  • cp .env.example .env

Ouvrez ce fichier en utilisant nano ou votre éditeur de texte préféré :

  • nano .env

Voici à quoi ressemble désormais votre fichier .env :

.env
APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password

Le fichier .env actuel de l'application de démonstration travellist contient les paramètres permettant d'utiliser l'environnement conteneurisé que nous avons créé avec Docker Compose dans la dernière partie de cette série. Vous n'avez besoin de modifier aucune de ces valeurs, mais vous êtes libre de modifier la DB_DATABASE, DB_USERNAME et DB_PASSWORD si vous le souhaitez, car elles sont tirées par notre fichier docker-compose.yml pour configurer automatiquement la base de données de développement. Assurez-vous simplement que la variable DB_HOST reste inchangée, car elle fait référence au nom de notre service de base de données dans l'environnement Docker Compose.

Si vous apportez des changements au fichier, veillez à l'enregistrer et à le fermer en pressant CTRL+X, Y, puis ENTER.

Remarque : si vous avez choisi de lancer l'application sur un serveur LEMP, vous devrez modifier les valeurs mises en évidence pour refléter les paramètres de votre propre base de données, y compris la variable DB_HOST.

Étape 3 - Installez les dépendances de l'application avec Composer

Nous allons maintenant utiliser Composer, l'outil de gestion des dépendances de PHP, pour installer les dépendances de l'application et nous assurer que nous sommes capables d'exécuter des commandes artisan.

Appelez votre environnement Docker Compose avec la commande suivante. Cela permettra de construire l'image travellist pour le service d’application et d'intégrer les images Docker supplémentaires requises par les services nginx et db, afin de créer l'environnement de l'application :

  • docker-compose up -d
Output
Creating network "travellist-demo_travellist" with driver "bridge" Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in 9259bb2ac034 … Creating travellist-app ... done Creating travellist-nginx ... done Creating travellist-db ... done

Cette opération peut prendre quelques minutes. Une fois le processus terminé, nous pouvons exécuter Composer pour installer les dépendances de l'application.

Pour exécuter composer et les autres commandes du conteneur du service d’application, nous utiliserons docker-compose exec. La commande exec nous permet d'exécuter toute commande de notre choix sur les conteneurs gérés par Docker Compose. Elle utilise la syntaxe suivante : docker-compose exec service_name command.

Remarque : si vous avez choisi d'utiliser un serveur LEMP pour exécuter l'application de démonstration, vous devez ignorer la partie docker-compose exec application des commandes énumérées dans ce guide. Par exemple, au lieu d'exécuter la commande suivante telle qu'elle est écrite, vous vous contenterez de lancer :

  • composer install

Pour exécuter composer install dans le conteneur d’application, exécutez :

  • docker-compose exec app composer install
Output
Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) …

Lorsque Composer aura terminé d'installer les dépendances de l'application, vous pourrez exécuter des commandes artisan. Pour vérifier que l'application est capable de se connecter à la base de données, exécutez la commande suivante qui nettoiera toutes les tables préexistantes :

  • docker-compose exec app php artisan db:wipe

Cette commande va déposer toute table préexistante dans la base de données configurée. Si elle a été exécutée avec succès et que l'application est capable de se connecter à la base de données, vous verrez une sortie comme ceci :

Output
Dropped all tables successfully.

Maintenant que vous avez installé les dépendances d'application avec Composer, vous pouvez utiliser l'outil artisan pour créer des migrations et seeders.

Étape 4 - Créez la base de données Migrations

L'outil de ligne de commande artisan qui est livré avec Laravel contient une série de commandes d'aide qui peuvent être utilisées pour gérer l'application et démarrer de nouvelles classes. Pour générer une nouvelle classe de migration, nous pouvons utiliser la commande make:migration comme suit :

  • docker-compose exec app php artisan make:migration create_places_table

Laravel déduit l'opération à exécuter (create), le nom de la table (places), et si cette migration créera ou non une nouvelle table, en fonction du nom descriptif fourni à la commande make:migration.

Vous verrez une sortie similaire à celle-ci :

Output
Created Migration: 2020_02_03_143622_create_places_table

Cela va générer un nouveau fichier dans le répertoire database/migrations de l'application. L'horodatage inclus dans le fichier généré automatiquement est utilisé par Laravel pour déterminer dans quel ordre les migrations doivent être exécutées.

Utilisez l'éditeur de texte de votre choix pour ouvrir le fichier de migration généré. N'oubliez pas de remplacer la valeur surlignée par votre propre nom de fichier de migration :

  • nano database/migrations/2020_02_03_143622_create_places_table.php

Le fichier de migration généré contient une classe appelée CreatePlacesTable :

database/migrations/2020_02_03_143622_create_places_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePlacesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('places', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('places');
    }
}

Cette classe a deux méthodes : up et down. Les deux méthodes contiennent du code de démarrage que vous pouvez étendre pour personnaliser ce qui se passe lorsque la migration est exécutée, et également ce qui se passe lorsqu'elle est annulée.

Nous allons modifier la méthode up afin que le tableau places reflète la structure que nous utilisons déjà dans la version actuelle de l'application :

  • id : champ clé primaire.
  • name : nom de la place
  • visited : si cette place a déjà été visitée ou non.

Le constructeur de schémas de Laravel expose des méthodes pour créer, mettre à jour et supprimer des tables dans une base de données. La classe Blueprint définit la structure du tableau et fournit plusieurs méthodes pour abstraire la définition de chaque champ de la table.

Le code généré automatiquement crée un champ d'identification primaire appelé id. La méthode timestamps crée deux champs datetime qui sont automatiquement mis à jour par les classes de base de données sous-jacentes lorsque des données sont insérées ou mises à jour dans ce tableau. En plus de ceux-ci, nous devrons inclure un champ name et un champ visited.

Notre champ name sera de type string , et notre champ visited sera défini avec le type boolean. Nous allons également fixer une valeur par défaut de 0 pour le champ visited, de sorte que si aucune valeur n'est passée, cela signifie que la place n'a pas encore été visitée. Voici à quoi ressemblera maintenant la méthode up :

database/migrations/2020_02_03_143622_create_places_table.php
…
    public function up()
    {
        Schema::create('places', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name', 100);
            $table->boolean('visited')->default(0);
            $table->timestamps();
        });
    }
…

Remarque : vous pouvez trouver la liste complète des types de colonnes disponibles dans la documentation Laravel.

Après avoir inclus les deux lignes sur votre propre script de migration, enregistrez et fermez le fichier.

Votre migration est maintenant prête à être exécutée via artisan migrate. Cependant, cela ne créerait qu'un tableau vide ; nous devons également pouvoir insérer des échantillons de données pour le développement et les tests. Au cours de la prochaine étape, nous allons voir comment faire cela en utilisant une base de données seeders.

Étape 5 - Créez la base de données Seeders

Un seeder est une classe spéciale utilisée pour générer et insérer des échantillons de données (seeds) dans une base de données. Il s'agit d'une caractéristique importante dans les environnements de développement, car elle permet de recréer l'application avec une base de données fraîche, en utilisant des valeurs d'échantillon que vous devriez autrement insérer manuellement à chaque fois que la base de données est recréée.

Nous allons maintenant utiliser la commande artisan afin de générer une nouvelle classe seeder pour notre tableau places appelé PlacesTableSeeder :

  • docker-compose exec app php artisan make:seeder PlacesTableSeeder

La commande va créer un nouveau fichier appelé PlacesTableSeeder.php à l'intérieur du répertoire database/seeds. Ouvrez ce fichier en utilisant l'éditeur de texte de votre choix :

  • nano database/seeds/PlacesTableSeeder.php

Voici à quoi ressemble le fichier PlacesTableSeeder.php généré automatiquement :

database/seeds/PlacesTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class PlacesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

Notre nouvelle classe seeder contient une méthode vide appelée run. Cette méthode sera appelée lorsque la commande Artisan db:seed sera exécutée.

Nous devons modifier la méthode run afin d'inclure des instructions pour insérer des échantillons de données dans la base de données. Nous utiliserons le constructeur de requêtes de Laravel pour rationaliser ce processus.

Le constructeur de requêtes Laravel offre une interface fluide pour les opérations de base de données telles que l'insertion, la mise à jour, la suppression et la récupération des données. Il introduit également des protections contre les attaques par injection SQL. Le constructeur de requête est exposé par la façade DB - un proxy statique aux classes de base de données sous-jacentes dans le conteneur de service.

Pour commencer, nous allons créer une variable de classe statique pour contenir tous les échantillons que nous voulons insérer dans la base de données sous la forme d'un tableau. Cela nous permettra d'utiliser une boucle foreach pour itérer toutes les valeurs, en insérant chacune d'entre elles dans la base de données à l'aide du constructeur de requêtes.

Nous allons appeller cette variable $places :

database/seeds/PlacesTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class PlacesTableSeeder extends Seeder
{
    static $places = [
        'Berlin',
        'Budapest',
        'Cincinnati',
        'Denver',
        'Helsinki',
        'Lisbon',
        'Moscow',
        'Nairobi',
        'Oslo',
        'Rio',
        'Tokyo'
    ];

Ensuite, nous devrons inclure une déclaration use en haut de notre classe PlacesTableSeeder pour faciliter le référencement de la façade DB dans tout le code :

database/seeds/PlacesTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class PlacesTableSeeder extends Seeder
…

Nous pouvons maintenant itérer les valeurs du tableau $places à l'aide d'une boucle foreach, et insérer chacune d'entre elles dans notre tableau places en utilisant le constructeur de requêtes :

database/seeds/PlacesTableSeeder.php
…
    public function run()
    {
        foreach (self::$places as $place) {
            DB::table('places')->insert([
                'name' => $place,
                'visited' => rand(0,1) == 1
            ]);
        }
    }

La boucle foreach se passe par chaque valeur du tableau statique $places. À chaque itération, nous utilisons la façade DB pour insérer une nouvelle rangée au tableau places. Nous avons défini le champ name au nom de la place que nous venons d'obtenir à partir du tableau $places, et nous avons défini le champ visited à une valeur aléatoire de 0 ou 1.

Voici à quoi ressemblera la classe PlacesTableSeeder complète après toutes les mises à jour :

database/seeds/PlacesTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class PlacesTableSeeder extends Seeder
{
    static $places = [
        'Berlin',
        'Budapest',
        'Cincinnati',
        'Denver',
        'Helsinki',
        'Lisbon',
        'Moscow',
        'Nairobi',
        'Oslo',
        'Rio',
        'Tokyo'
    ];

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        foreach (self::$places as $place) {
            DB::table('places')->insert([
                'name' => $place,
                'visited' => rand(0,1) == 1
            ]);
        }
    }
}

Enregistrez et fermez le fichier lorsque vous avez terminé de procéder à ces changements.

Les classes Seeder ne sont pas automatiquement chargées dans l'application. Nous devons modifier la classe DatabaseSeeder principale pour inclure un appel au seeder que nous venons de créer.

Ouvrez le fichier database/seeds/DatabaseSeeder.php à l'aide de nano ou de votre éditeur préféré :

  • nano database/seeds/DatabaseSeeder.php

La classe DatabaseSeeder ressemble à n'importe quel autre seeder : elle s'étend depuis la classe Seeder et a une méthode run. Nous allons mettre à jour cette méthode pour inclure un appel à PlacesTableSeeder.

Mettez à jour la méthode run actuelle dans votre classe DatabaseSeeder en supprimant la ligne commentée et en la remplaçant par le code sélectionné qui suit :

database/seeds/DatabaseSeeder.php
…
    public function run()
    {
        $this->call(PlacesTableSeeder::class);
    }
...

Voici à quoi ressemblera la classe DatabaseSeeder complète après la mise à jour :

database/seeds/DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(PlacesTableSeeder::class);
    }
}


Enregistrez et fermez le fichier lorsque vous avez terminé de mettre à jour son contenu.

Nous avons maintenant terminé de créer à la fois une migration et un seeder pour notre tableau places. Au cours de la prochaine étape, nous allons voir comment les exécuter.

Étape 6 - Exécutez la base de données Migrations et Seeders

Avant de poursuivre, nous devons nous assurer que votre application est opérationnelle. Nous allons configurer la clé de cryptage de l'application, puis accéder à l'application à partir d'un navigateur pour tester le serveur web.

Pour générer la clé de cryptage requise par Laravel, vous pouvez utiliser la commande artisan key:generate :

  • docker-compose exec app php artisan key:generate

Une fois la clé générée, vous pourrez accéder à l'application en pointant votre navigateur vers votre serveur hostname ou votre adresse IP sur le port 8000 :

http://server_host_or_ip:8000

Vous verrez une page comme celle-ci :

MySQL error

Cela signifie que l'application est capable de se connecter à la base de données, mais qu'elle n'a pu trouver le tableau places. Nous allons créer maintenant le tableau places, en utilisant la commande artisan migrate suivante :

  • docker-compose exec app php artisan migrate

Vous aurez une sortie similaire à celle-ci :

Output
Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)

Vous remarquerez que quelques autres migrations ont été exécutées en même temps que la migration create_places_table que nous avons mise en place. Ces migrations sont générées automatiquement lors de l'installation de Laravel. Même si nous n'utiliserons pas ces tableaux supplémentaires maintenant, ils seront nécessaires à l'avenir lorsque nous étendrons l'application pour inclure des utilisateurs enregistrés et des jobs programmés. Pour l'instant, vous pouvez simplement les laisser tels quels.

À ce stade, notre tableau est toujours vide. Nous devons exécuter la commande db:seed pour seeder la base de données avec notre échantillon de places :

  • docker-compose exec app php artisan db:seed

Cela va exécuter notre seeder et insérer les échantillons des valeurs que nous avons définies dans notre classe PlacesTableSeeder. Vous verrez une sortie similaire à celle-ci :

Output
Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

Maintenant, rechargez la page de l'application sur votre navigateur. Vous verrez une page similaire à celle-ci :

application de démonstration Laravel

Chaque fois que vous devez repartir de zéro, vous pouvez déposer tous vos tableaux de base de données avec :

  • docker-compose exec app php artisan db:wipe
Output
Dropped all tables successfully.

Pour lancer les apps de migration et seeder les tableaux en une seule commande, vous pouvez utiliser :

  • docker-compose exec app php artisan migrate --seed
Output
Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully.

Si vous voulez annuler une migration, vous pouvez exécuter :

  • docker-compose exec app php artisan migrate:rollback

Cela déclenchera la méthode down pour chaque classe de migration dans le dossier migrations. En général, cela supprime tous les tableaux qui ont été créées par les classes de migration, en ignorant tous les autres tableaux qui auraient pu être créés manuellement. Vous verrez une sortie de ce type :

Output
Rolling back: 2020_02_10_144134_create_places_table Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds) Rolling back: 2019_08_19_000000_create_failed_jobs_table Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)

La commande rollback est particulièrement utile lorsque vous apportez des modifications aux modèles d'application et qu'une commande db:wipe ne peut pas être utilisée - par exemple, si plusieurs systèmes dépendent de la même base de données.

Conclusion

Dans ce guide, nous avons vu comment utiliser les bases de données migrations et seeders afin faciliter la mise en place de bases de données de développement et de test pour une application Laravel 6.

Pour continuer, vous pourriez consulter la documentation de Laravel pour plus de détails sur la façon d'utiliser le constructeur de requêtes et d'utiliser les modèles Eloquent afin d'abstraire encore davantage le schéma de la base de données de votre application.

0 Comments

Creative Commons License