30
loading...
This website collects cookies to deliver better user experience
N
number of records by just passing N
as a parameter when calling the factory()
method. Besides that, you can create data for related models using factories that were not possible with the seeders.make:model
command by default uses the HasFactory
trait which provides access to the factory()
method. This method accepts a number as a parameter to generate that many records for the table. database/factories
directory. This directory by default contains a file UserFactory.php
which defines the UserFactory
class. Every factory class has a method definition()
that returns a set of model attributes with default values as fake data. Laravel uses Faker PHP library to generate dummy data.<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function unverified()
{
return $this->state(function (array $attributes) {
return [
'email_verified_at' => null,
];
});
}
}
php artisan tinker
>>> \App\Models\User::factory()->create();
=> App\Models\User {#4532
name: "Blanca Feeney",
email: "[email protected]",
email_verified_at: "2021-12-23 19:01:43",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "Q2J7GmXoGH",
updated_at: "2021-12-23 19:01:43",
created_at: "2021-12-23 19:01:43",
id: 2,
}
>>>
factory()
method will create just one record. But if we supply a number to it, it will create that many records.>>> \App\Models\User::factory(3)->create();
=> Illuminate\Database\Eloquent\Collection {#4550
all: [
App\Models\User {#4554
name: "Gino Beatty",
email: "[email protected]",
email_verified_at: "2021-12-23 19:03:55",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "5Cnxmjmc9D",
updated_at: "2021-12-23 19:03:55",
created_at: "2021-12-23 19:03:55",
id: 3,
},
App\Models\User {#4555
name: "Piper Schmitt",
email: "[email protected]",
email_verified_at: "2021-12-23 19:03:55",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "6zgiY9uPO6",
updated_at: "2021-12-23 19:03:55",
created_at: "2021-12-23 19:03:55",
id: 4,
},
App\Models\User {#4556
name: "Lance Skiles III",
email: "[email protected]",
email_verified_at: "2021-12-23 19:03:55",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "IWqf0v15Gb",
updated_at: "2021-12-23 19:03:55",
created_at: "2021-12-23 19:03:55",
id: 5,
},
],
}
>>>
UserFactory
, it's time to create our own brand new factory class using the Artisan command make:factory
.php artisan make:factory PostFactory
database/factories
directory. One other way of creating a factory class is to create it with the Artisan command make:model
as an option --factory
or just -f
.php artisan make:model Post -f
PostFactory
class. Before we modify it, see the PostFactory
class as it was generated with the Artisan command make:factory
.<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
//
}
}
definition()
method yet. We need to return
an array of model attributes with fake values from this method. So, let's add it.<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
"user_id" => \App\Models\User::factory(),
"category_id" => Category::factory(),
"title" => $this->faker->sentence(),
"slug" => $this->faker->slug(),
"excerpt" => $this->faker->sentence(),
"body" => $this->faker->sentence()
];
}
}
Faker
library here. If we call this factory now in tinker \App\Models\Post::factory()->create()
it will throw an error about the Category
factory not found. Notice that here we are not only generating data for our Post
model but also for our related models User
and Category
too. It is the power of factories that Seeders don't have.UserFactory
out of the box. So, let's create the CategoryFactory
in order for the above command to work.php artisan make:factory CategoryFactory
CategoryFactory
it looks like this.<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class CategoryFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
"title" => $this->faker->word(),
"slug" => $this->faker->word()
];
}
}
php artisan tinker
and call the Post
model factory()
to create records for the Post
model as:>>> \App\Models\Post::factory()->create()
=> App\Models\Post {#4591
user_id: 1,
category_id: 1,
title: "Qui tenetur architecto nihil omnis.",
slug: "hic-itaque-itaque-unde-ut-ratione-in-tempore",
excerpt: "Non unde voluptatem ipsam reprehenderit.",
body: "Impedit voluptates aut quae sit ut ut consequatur.",
updated_at: "2021-12-24 09:09:34",
created_at: "2021-12-24 09:09:34",
id: 1,
}
>>>
User
and Category
models and assigned their id
s to the foreign keys user_id
and category_id
for the Post
model.User
and Category
data crated with the Post
model above could be Eager Loaded or included with the Post
model as:>>> \App\Models\Post::with("user", "category")->first()
=> App\Models\Post {#3630
id: 1,
user_id: 1,
category_id: 1,
title: "Dicta id maiores amet officia doloribus quae nesciunt.",
slug: "voluptas-voluptatem-voluptates-aut-et-quia-veritatis-molestias",
excerpt: "Dolores deleniti esse accusantium exercitationem dolorum.",
body: "Reprehenderit magnam sed architecto maxime quis inventore.",
published_at: null,
created_at: "2021-12-23 18:51:53",
updated_at: "2021-12-23 18:51:53",
user: App\Models\User {#4572
id: 1,
name: "John Doe",
email: "[email protected]",
email_verified_at: "2021-12-23 18:51:53",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "rRCNWU09wU",
created_at: "2021-12-23 18:51:53",
updated_at: "2021-12-23 18:51:53",
},
category: App\Models\Category {#4577
id: 1,
title: "porro",
slug: "sint",
created_at: "2021-12-23 18:51:53",
updated_at: "2021-12-23 18:51:53",
},
}
>>>
User
and Category
models included in the Post
model. It is because we already have defined the relationships between these models.\App\Models\User::factory()->create([])
will create a User
record with the fake attribute values as defined in the UserFactory
. But what if we want the name of the user to override the fake name with a pre-defined name like John Doe
? We can do that like so.\App\Models\User::factory()->create([
'name' => "John Doe"
]);
Post
record is created, we pass a specific user to the PostFactory
as:$user = \App\Models\User::factory()->create([
'name' => "John Doe"
]);
Post::factory(5)->create([
"user_id" => $user->id
]);
database/seeders/DatabaseSeeder.php
class run()
method content with the above code and run the following command.php artisan migrate:fresh --seed
5
fresh records of the Post
model with 5
Category
and 1
User
records. As we passed a pre-defined User
to the Post
factory, so, instead of creating a new user for each post and assign it, the specified user will be assigned to each post.