Insert mass database records using model factories in Laravel
One of the many ways using which you can insert records (or seed your database) is by using the seeder classes which extend a base class called Illuminate\Database\Seeder
in Laravel.
For instance, if you want a seeder for say books
table, you can generate it using the following command like so.
$ php artisan make:seeder BookSeeder
This will generate the seeder class under the database/seeds
directory which looks like the following.
<?php
use Illuminate\Database\Seeder;
class BookSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
}
}
Now, the class only contains a method called run
and this is where you can write queries to insert records like so.
public function run()
{
DB::table('books')->insert([
'name' => Str::random(10),
'author' => Str::random(10),
'type' => Str::random(10),
]);
}
Now, whenever you run the seeders, it will add a record in the books
table with random values as shown above. This alright but what if you want more records for your testing purposes? You certainly won’t repeat multiple insert
queries inside of the run
, right?
And this is where model factories come into the picture.
Model Factories
In a nutshell, model factories are nothing but PHP files (not classes) using which Laravel allows you to set a default set of attributes for each of your Eloquent models.
A factory can be generated by using make:factory
Artisan command. So, if we want to generate a factory for our Book
model, we can generate it like so.
$ php artisan make:factory BookFactory
This will generate a PHP file called BookFactory.php
under database/factories
directory and it would look like so.
<?php
use App\Book;
use Illuminate\Support\Str;
use Faker\Generator as Faker;
$factory->define(Book::class, function (Faker $faker) {
$type = ['fiction', 'nonfiction'];
return [
'name' => $faker->word,
'author' => $faker->name,
'type' => $type[rand(0, (count($type)-1))]
];
});
As you can see, Laravel gives us Faker PHP library at our disposal in the factory definition which is a Closure. Here, we can set the default values for attributes by returning an attributes array using the Faker library. Once done, we can now use this factory as a base to our BookSeeder
which will generate database records using factory definition.
For instance, if you want to generate, say 20 records based on this factory, you can use it in the BookSeeder
like so.
public function run()
{
factory(App\Book::class, 20)->create()->each(function ($book) {
$book->save(factory(App\Book::class)->make());
});
}
This will generate 20 records for the books
table without cluttering your code too much and is also easy to maintain.
Of course, you can also attach a relationship over here. So, if we want to attach a sales relationship, you can do it like so.
$book->sales()->save(factory(App\Book::class)->make());
Like this article?
Buy me a coffee👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.