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.