Laravel : Générer des données de test avec Factory, Faker et Tinker

Mis à jour il y a 1 an

Un tutoriel pour insérer des données aléatoires générées par les Factories et Faker dans une base de données en utilisant Tinker dans un projet Laravel.

Wilo Ahadi

Auteur

Wilo A.

Technologies

Laravel, PHP
Voir aussi Un tutoriel pour définir votre propre page d'erreur 404 pour les requêtes entrantes qui ne correspondent pas aux routes enregistrées dans un projet Laravel En savoir plus

Introduction

Lors du développement d'applications Web, vous avez besoin de données pour tester les fonctionnalités. La saisie de ces données séparément dans une table de base de données est fastidieuse. Le framework PHP Laravel résout ce problème en fournissant des factories. 

Un factory est une classe qui permet de générer des données de manière aléatoire pour les tests ou pour remplir une base de données. En combinant un factory avec la librairie Faker, nous pouvons générer des données réalistes et structurées tels que des noms, des adresses email, des numéros de téléphones, des paragraphes,  ...

Nous allons voir dans ce tutoriel comment générer des données en masse pour tester une application et les insérer dans la base de données en utilisant les factories, Faker et Tinker dans un projet Laravel.

Au moment de la rédaction de cet article, j'utilise la version 10.7.1 de Laravel.

La version anglaise de cette publication : Laravel: Generating test data with Factory, Faker and Tinker

Exemple d'un factory

Dans un nouveau projet Laravel, nous avons par défaut le factory database\factories\UserFactory.php du modèle App\Models\User.php :

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }

    public function unverified(): static
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
}

Dans ce code source, la méthode definition() retourne le tableau des valeurs d'attributs qui doivent être appliquées lors de la création d'un modèle.

L'helper fake() permet d'accéder à la librairie Faker qui génère des données aléatoires. L'instruction faker()->name() génère un nom aléatoire et faker()->unique()->safeEmail() une adresse email aléatoire unique.

La documentation de Faker présente les différents formats de données que vous pouvez générer.

Créer un factory

Pour créer un factory dans un projet Laravel, on exécute la commande Artisan suivante :

php artisan make:factory ModelFactory --model=Model

Model représente un modèle dans le répertoire App\Models. Dans l'exemple précédent, le factory UserFactory a été généré avec la commande :

php artisan make:factory UserFactory --model=User

Pour créer le factory d'un modèle App\Models\Post.php, on exécute la commande :

php artisan make:factory PostFactory --model=Post

Cette commande crée le fichier database\factories\PostFactory.php.

Imaginez que le modèle Post ait un attribut title pour le titre, content pour le contenu et user_id pour l'identifiant de l'utilisateur. Vous pouvez utiliser Faker via fake() dans la méthode definition() de PostFactory.php pour générer des données aléatoires et réalistes pour ces attributs, comme ceci :  

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\User;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            "title" => fake()->sentence(5), // Une phrase de 5 mots
            "content" => fake()->text(), // Une chaîne de texte de 200 caractères (par défaut)
            "user_id" => User::inRandomOrder()->first() // Un utilisateur enregistré pris aléatoirement
        ];
    }
}

Remplir la base de données avec Tinker

Maintenant que les factories sont prêts, nous allons utiliser Tinker pour insérer les données des modèles User.php et Post.php dans la base de données. Tinker est une interface en ligne de commande (CLI) qui vous permet d'interagir avec votre application Laravel à l'aide de commandes PHP directement dans votre terminal.

Pour accéder à Tinker, exécutez la commande Artisan suivante à la racine de votre projet :

php artisan tinker

Une fois dans Tinker, vous pouvez utiliser la méthode statique factory() sur créer une instance Factory pour un modèle et la méthode make() pour créer des modèles sans les enregistrer dans la base de données :

$user = User::factory()->make()
$post = Post::factory()->make()

Pour obtenir une collection, on utilise la méthode count($n) pour $n modèles :

$user = User::factory()->count(3)->make() // Collection de 3 User
$post = Post::factory()->count(5)->make() // Collection de 5 Post

Sauvegarder dans la base de données

Vous pouvez générer des informations aléatoires pour 3 User et les insérer dans la base de données à l'aide de la méthode create() :

User::factory()->count(3)->create() // Création de 3 users

La commande suivante génère des informations aléatoires pour 1000 Post et les insère dans la base de données :

Post::factory()->count(1000)->create() // Création de 1000 posts

Relations des modèles avec Factory

Les factories permettent de générer des données basées sur les relations entre les modèles. Les relations telles que « Has Many » (a plusieurs), « Belongs To » (appartient à), « Many To Many » (plusieurs à plusieurs) et « Polymorphic » (polymorphe) sont prises en charge, mais ce tutoriel sera limité aux relations « Has Many » et « Belongs To ».  Le reste se trouve dans la documentation Laravel Eloquent: Factories.

Relation "Has Many"

Si vous avez défini une relation "has many" entre les modèles User et Post dans App\Models\User.php :

public function posts () {
    return $this->hasMany(Post::class);
}

Vous pouvez générer un utilisateur en l'associant à plusieurs publications générées simultanément dans Tinker de la manière suivante :

User::factory()->has(Post::factory()->count(5))->create() // 5 publications générées pour un nouvel utilisateur

La méthode has($posts) spécifie le modèle parent des modèles générés par le factory.

Méthode magique

Pour plus de simplicité, vous pouvez utiliser la méthode magique de relation du factory hasModels($n) pour définir la relation "Has Many" :

User::factory()->hasPosts(5)->create()

Relation "belongs To"

Si vous avez défini une relation "belongs To" entre les modèles Post et User dans App\Models\Post.php :

public function user () {
    return $this->belongsTo(User::class);
}

Vous pouvez générer des publications en les associant à un utilisateur dans Tinker de la manière suivante :

Post::factory()->for(User::factory()->create())->count(25)->create() // Création d'un nouvel utilisateur
Post::factory()->for(User::first())->count(25)->create() // Utilisation d'un utilisateur déjà enregistré

La méthode for($user) spécifie le modèle parent auquel appartiennent les modèles générés par le factory.

Méthode magique

Pour plus de simplicité, vous pouvez utiliser la méthode magique de relation du factory forModel($model) pour définir la relation "Belongs To" et spécifier le modèle parent :

Post::factory()->forUser([ "name" => "Wilo Ahadi" ])->count(1)->create() // Création d'un nouvel utilisateur de nom "Wilo Ahadi"

Portez-vous bien.

Cette publication vous a plu ?
Partagez-la avec vos ami(e)s sur les réseaux sociaux.

Wilo Ahadi

Wilo Ahadi, l'auteur

Passionné de l'informatique, je suis spécialiste en techniques des systèmes et réseaux, développeur web et mobile, infographiste et designer, ... J'aime partager mon expérience en formant sur la plateforme Akili School

Voir profil

Commentaires