A tutorial to insert random data generated by Factories and Faker into a database using Tinker in a Laravel project.

The French version of this publication : Laravel : Générer des données de test avec Factory, Faker et Tinker

Introduction

When developing web applications, you need data to test functionality. Entering this data separately in a database table is tedious. The Laravel PHP framework solves this problem by providing factories.

A factory is a class that allows to generate data in a random way for tests or to fill a database. By combining a factory with the Faker library, we can generate realistic and structured data such as names, email addresses, phone numbers, paragraphs, ...

In this tutorial we will see how to use factories, Faker and Tinker in a Laravel project to generate bulk data for testing an application and adding it to the database.

At the time of writing this article, I am using version 10.7.1 of Laravel.

Example of a factory

In a new Laravel project, we have by default the factory database\factories\UserFactory.php of the model 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,
        ]);
    }
}

In this source code, the definition() method returns the array of attribute values that must be applied when creating a model.

The helper fake() provides access to the Faker library which generates random data. The instruction faker()->name() generates a random name and faker()->unique()->safeEmail() a unique random email address.

The Faker documentation outlines the different data formats you can generate.

Create a factory

To create a factory in a Laravel project, we run the following Artisan command:

php artisan make:factory ModelFactory --model=Model

Model represents a model in the directory App\Models. In the previous example, the UserFactory was generated with the command :

php artisan make:factory UserFactory --model=User

To create the factory of a model App\Models\Post.php, we execute the command :

php artisan make:factory PostFactory --model=Post

This command creates the database\factories\PostFactory.php file.

Imagine that the Post model has a title attribute for the title, content for the content and user_id for the user ID. You can use Faker via fake() in the definition() method of PostFactory.php to generate random and realistic data for these attributes, like this:

<?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), // A 5-word sentence
            "content" => fake()->text(), // A text string of 200 characters (default)
            "user_id" => User::inRandomOrder()->first() // A registered user taken at random
        ];
    }
}

Populate the database with Tinker

Now that the factories are ready, we'll use Tinker to insert the data of the User.php and Post.php models into the database. Tinker is a command line interface (CLI) that allows you to interact with your Laravel application using PHP commands directly in your terminal.

To access Tinker, run the following Artisan command at the root of your project:

php artisan tinker

Once in Tinker, you can use the static factory() method to create a Factory instance for a model and the make() method to create models without saving them to the database:

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

To obtain a collection, we use the method count($n) for $n models:

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

Save to database

You can generate random information for 3 User and insert them into the database using the create() method:

User::factory()->count(3)->create() // Creation of 3 users

The following command generates random information for 1000 Post and inserts them into the database:

Post::factory()->count(1000)->create() // Creation of 1000 posts

Relationship of models with Factory

Factories allow you to generate data based on relationships between models. Relationships such as "Has Many", "Belongs To", "Many To Many" and "Polymorphic" are supported, but this tutorial will be limited to "Has Many" and "Belongs To" relationships.  The rest can be found in the Laravel documentation Eloquent: Factories.

"Has Many" relationship

If you have defined a "has many" relationship between the User and Post models in App\Models\User.php :

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

You can generate a user by associating him/her with several publications generated simultaneously in Tinker in the following way:

User::factory()->has(Post::factory()->count(5))->create() // 5 publications generated for a new user

The method has($posts) specifies the parent model of the models generated by the factory.

Magic method

For simplicity, you can use the magic relationship method of the factory hasModels($n) to define the relationship "Has Many":

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

"belongs To" relationship

If you have defined a "belongs To" relationship between the Post and User models in App\Models\Post.php :

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

You can generate posts by associating them with a user in Tinker in the following way:

Post::factory()->for(User::factory()->create())->count(25)->create() // Creating a new user
Post::factory()->for(User::first())->count(25)->create() // Use of an already registered user

The for($user) method specifies the parent model to which the models generated by the factory belong.

Magic method

For simplicity, you can use the magic relationship method of the factory forModel($model) to define the "Belongs To" relationship and specify the parent model:

Post::factory()->forUser([ "name" => "Wilo Ahadi" ])->count(1)->create() // Creation of a new user with the name "Wilo Ahadi".

Be well.