How to use Laravel Seeders, Fakers, and Factories

Lonare
8 min readJun 25, 2021

--

I have been working on a new project in the evenings and realised that whenever I move my app to a new server or even a localenvironment. I have to export the whole MySql database and then import it back to the new server.

After looking for a while I found that Laravel actually provides a super quick solution for you to actually create your database structure as well as generate fake data.

Isn’t thats great.

If you’re just starting out with Laravel, some of the first few questions that you’ll come across are:

  • What is the difference between Seeders, Fakers, and Factories?
  • Should I use them?
  • Do I need to use all of them or can I use some of them?
  • How do I create them?

If you’re looking up the answers to these questions, I would assume that you have Laravel already installed. If you don’t, and don’t know how, you can follow the steps in my other article:

Factories

According to Laravel’s official documentation, “factories are classes that extend Laravel’s base factory class and define a model property and definition method.” Just think about it this way. If you’ve ever created a model, like the User’s model (App\Models\User), you’ll know that certain fields should be populated when you use the create() method.

In the example above, we provide the name, email, and password fields to the User model to populate the users table. A factory will just define a standard way for us to do this. This is incredibly helpful when you’re testing your application.

In your tests, you might have hundreds of places where you have to generate a new user. If you ever change your code, you’ll have to change it in hundreds of different places (for example, adding roles to your users). You’re just creating a test user so you can leverage a factory where it will create that test user for you.

Laravel has already created a User factory for us. It’s located in database/factories/UserFactory.php.

The UserFactory utilizes Faker, which we won’t use in this example. Let’s modify the code in the definition() method to use a static name and email.

You can see that the definition() method just returns an array…almost like the array that we can pass to the create() method in our User model.

To call a factory, we can “use the static factory method provided by the Illuminate\Database\Eloquent\Factories\HasFactory trait on our Eloquent model.” In our case, User::factory()->make(). How does the User model know which factory it should use? It was defined at the top of the factory:

To test this, open up tinker:

php artisan tinker

Run the factory command:

User::factory()->make();

You should get a response similar to this:

=> App\Models\User {#3477
name: "Dino Cajic",
email: "dinocajic@gmail.com",
email_verified_at: "2020-10-19 14:58:29",
}

This creates the User model; it doesn’t actually save it to the database. To save it to the database, you can use create() instead of make().

User::factory()->create();

You can verify that the user exists by looking at the users table in your database.

And that’s it. When you’re creating your tests, you can use the factory command to create any new instance of a user wherever you need it.

This approach will create a new user with the same name and email each time. What if you wanted a random name and a unique email each time? That’s where faker comes in.

Fakers

You can start using the faker library automatically. The Faker PHP library is pretty powerful and makes generating random names, emails, etc, incredibly easy. You can read the Faker documentation to find out more.

In our case, we just want a random name and a unique email. We can return the code in the UserFactory to its original state.

We can test to make sure that it’s working by running the same factory()->make() command in tinker. You can run this code as many times as you’d like and faker will generate new users each time.

php artisan tinker>>> User::factory()->make();
=> App\Models\User {#3477
name: "Mr. Milo Jast MD",
email: "herzog.mose@example.org",
email_verified_at: "2020-10-19 15:13:31",
}
>>> User::factory()->make();
=> App\Models\User {#3476
name: "Carolanne Hettinger",
email: "eladio62@example.org",
email_verified_at: "2020-10-19 15:13:34",
}

You can now use your factory with faker to generate random users whenever you need them just like before.

What if you wanted to generate 50 users? Laravel makes this painless as well. Let’s look at it in tinker again.

php artisan tinker>>> User::factory()->count(50)->make();=> Illuminate\Database\Eloquent\Collection {#3474
all: [
App\Models\User {#3479
name: "Geovanni Brakus",
email: "xokuneva@example.com",
email_verified_at: "2020-10-19 15:27:23",
},
App\Models\User {#3480
name: "Dr. Clara Nienow",
email: "jerde.orval@example.net",
email_verified_at: "2020-10-19 15:27:23",
},
App\Models\User {#3481
name: "Prof. Stephon Ziemann IV",
email: "sonia.mitchell@example.org",
email_verified_at: "2020-10-19 15:27:23",
},
App\Models\User {#3482
name: "Katrina O'Kon",
email: "jessika.gaylord@example.org",
email_verified_at: "2020-10-19 15:27:23",
},
App\Models\User {#3483
name: "Marlen Rosenbaum",
email: "hartmann.edwina@example.org",
email_verified_at: "2020-10-19 15:27:23",
},
...

And just like that, you have 50 new users with the help of the count() method that’s been chained on. You can also persist the data by using the create() method.

php artisan tinker>>> User::factory()->count(50)->create();

Check the users table in your database to verify that you have 50 new users.

Creating a Factory and Utilizing Faker

Up until now, we’ve looked at the User model. Let’s create a new model and factory at the same time.

php artisan make:model Car -mf
Model created successfully.
Factory created successfully.
Created Migration: 2020_10_19_154353_create_cars_table

This command will generate a model Car with a migration (-m) and a factory (-f). First, open up the car migration (database/migrations/create_cars_table…php) and let’s define the make and model of the vehicle.

Run the migration.

php artisan migrate

Now that we have the cars table created with the make and model fields, let’s populate the table. We’ll have to make the make and model fields writable by going to our Car model (App\Models\Car) and adding the fields into our $fillable property.

Open CarFactory (database/factories/CarFactory.php).

The definition is empty and is ready for us to populate. All we care about is that the make and the model are strings. We can use faker to help us with that.

Let’s see if it works. Open up tinker and run the factory()->create() command to persist the data.

php artisan tinker>>> Car::factory()->count(3)->create();=> Illuminate\Database\Eloquent\Collection {#3474
all: [
App\Models\Car {#3478
make: "delectus",
model: "commodi",
updated_at: "2020-10-19 16:02:35",
created_at: "2020-10-19 16:02:35",
id: 1,
},
App\Models\Car {#3479
make: "illo",
model: "voluptates",
updated_at: "2020-10-19 16:02:35",
created_at: "2020-10-19 16:02:35",
id: 2,
},
App\Models\Car {#3480
make: "qui",
model: "nostrum",
updated_at: "2020-10-19 16:02:35",
created_at: "2020-10-19 16:02:35",
id: 3,
},
],
}

Check the cars table in your database and voilà, it’s there.

Creating a Factory after the Model has been created

If you forgot to create your factory when you created your model, you can always create it after the fact.

php artisan make:factory CarFactory --model=Car

The — model flag tells the CarFactory which model it’s for. If you forgot to include the — model flag, you would have to modify the CarFactory and include the model manually.

So far so good. You can now create fake data in one place and populate your tables as many times as you want. What if you wanted to populate some data inside your database before you started testing/using your application? You could just run ModelName::factory()->count(20)->create() for each database table before you start using your application. What if you had a dozen tables? You would have to run a dozen commands before each test. What if you had hundreds of tables? This is where seeders come into play.

Seeders

The seeder will populate your database tables when you run the following command:

// Can call multiple seeders
php artisan db:seed

You can also call an individual seeder:

php artisan db:seed --class=UserSeeder

Let’s create a seeder and see how this all ties in. Run the following command to create a User Seeder:

php artisan make:seeder UserSeeder

Artisan will generate a new class called UserSeeder under database/seeders/UserSeeder.php.

It’s just a class with an empty run() method. The run() method is where we’ll add all of our code to see the database. Let’s first populate the users table without using factories.

As you can probably guess, this will insert a new record into the users table. Let’s call the seeder and verify that the data persists:

php artisan db:seed --class=UserSeeder

Checking the database table, I can verify that the new record is there.

We’re starting to add code into multiple places again. As you can see, the run() method just runs whatever’s inside of it when the db:seed command is issued. So why can’t it just run our factory command? Well it can, and it will, as many times as we want it to.

The code above will store 10 new random entries (thanks to faker) inside of our database. Let’s run the same command again and verify that they’re there.

php artisan db:seed --class=UserSeeder

Let’s create another seeder for our Car model and utilize the CarFactory that we created earlier.

php artisan make:seeder CarSeeder

We can run the db:seed command to populate the cars table with 50 new entries.

php artisan db:seed --class=CarSeeder

Verify that the cars table contains 50 new rows.

At this point, you can probably see the value of running multiple seeders with one command. If you had 50 seeders, you wouldn’t want to run 50 different commands. Luckily, Laravel addresses that issue as well.

You’ve probably noticed another class that was automatically created by Laravel called DatabaseSeeder (database/seeders/DatabaseSeeder.php).

You could uncomment the code and call the User factory directly from here, or you could use the call() method to call each of the seeders. According to Laravel’s documentation, “using the call method allows you to break up your database seeding into multiple files so that no single seeder class becomes overwhelmingly large.”

Let’s pass our UserSeeder and CarSeeder to the call() method. The call() method accepts an array as an argument where each element is the seeder class that you want to call.

We can now use the following command to call the DatabaseSeeder which will in turn call each of our specified seeders:

php artisan db:seed
Seeding: Database\Seeders\UserSeeder
Seeded: Database\Seeders\UserSeeder (26.58ms)
Seeding: Database\Seeders\CarSeeder
Seeded: Database\Seeders\CarSeeder (14.14ms)
Database seeding completed successfully.

Artisan will provide us with messages letting us know that everything went well. You can also verify that the database tables have been seeded visually.

If you have too much data in your database tables already, you can always clear them out before running the seeder. You may want to do this each time anyway:

php artisan migrate:fresh --seed

I hope that this article has helped to demystify Seeders, Fakers, and Factories for you.

--

--

Lonare
Lonare

Written by Lonare

Imagination is the key to unlock the world. I am trying to unlock mine.