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?

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.

User::create([
    'name' => $input['name'],
    'email' => $input['email'],
    'password' => Hash::make($input['password']),
]);

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.

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * 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,
            ];
        });
    }
}

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.

return [
    'name' => 'Orkhan Alishov',
    'email' => 'hi@alishoff.com',
    'email_verified_at' => now(),
    'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
    'remember_token' => Str::random(10),
];

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:

protected $model = User::class;

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 {#3489
     name: "Orkhan Alishov",
     email: "hi@alishoff.com",
     email_verified_at: "2021-08-30 08:26:59",
     #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
     #remember_token: "F1CI7FsnHl",
   }

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.

use App\Models\User;

public function testDatabase()
{
    $user = User::factory()->make();

    // Use model in tests...
}

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.

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.

C:\xampp\htdocs\laravel-test.com>php artisan tinker
Psy Shell v0.10.8 (PHP 7.4.19 — cli) by Justin Hileman
>>> User::factory()->make();
[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
=> App\Models\User {#3489
     name: "Damien Harvey PhD",
     email: "wendell53@example.org",
     email_verified_at: "2021-08-30 08:34:16",
     #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
     #remember_token: "UpSIHtKDVx",
   }
>>> User::factory()->make();
=> App\Models\User {#3497
     name: "Dr. Laverna Hirthe V",
     email: "mike.ward@example.net",
     email_verified_at: "2021-08-30 08:34:18",
     #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
     #remember_token: "qqLOGA3aIl",
   }
>>> User::factory()->make();
=> App\Models\User {#3483
     name: "Mr. Jared Schmeler V",
     email: "travis39@example.com",
     email_verified_at: "2021-08-30 08:34:19",
     #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
     #remember_token: "GKLZGA4pDZ",
   }

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

use App\Models\User;

public function testDatabase()
{
    $user = User::factory()->make();

    // Use model in tests...
}

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

C:\xampp\htdocs\laravel-test.com>php artisan tinker
Psy Shell v0.10.8 (PHP 7.4.19 — cli) by Justin Hileman
>>> User::factory()->count(5)->make();
[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
=> Illuminate\Database\Eloquent\Collection {#3487
     all: [
       App\Models\User {#3491
         name: "Jermaine Bode MD",
         email: "zokuneva@example.net",
         email_verified_at: "2021-08-30 08:36:36",
         #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
         #remember_token: "Evwt3nuNtK",
       },
       App\Models\User {#3498
         name: "General Aufderhar",
         email: "oma.pollich@example.net",
         email_verified_at: "2021-08-30 08:36:36",
         #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
         #remember_token: "UCT6GV6CPG",
       },
       App\Models\User {#3499
         name: "Reta Koch",
         email: "buddy.hills@example.com",
         email_verified_at: "2021-08-30 08:36:36",
         #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
         #remember_token: "gHebCuxqKB",
       },
       App\Models\User {#3500
         name: "Dina Pfannerstill",
         email: "gertrude.reynolds@example.com",
         email_verified_at: "2021-08-30 08:36:36",
         #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
         #remember_token: "0jAdMlR2Z2",
       },
       App\Models\User {#3501
         name: "Ms. Ardith Ferry",
         email: "lawrence.williamson@example.org",
         email_verified_at: "2021-08-30 08:36:36",
         #password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
         #remember_token: "GNVzwUGZzw",
       },
     ],
   }

And just like that, you have 5 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(5)->create();

Check the users table in your database to verify that you have 5 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.

C:\xampp\htdocs\laravel-test.com>php artisan make:model Car -mf
Model created successfully.
Factory created successfully.
Created Migration: 2021_08_30_084412_create_cars_table

This command will generate a model Car with a migration (-m) and a factory (-f). First, open up the car migration file and let's define the make and model of the vehicle.

public function up()
{
    Schema::create('cars', function (Blueprint $table) {
        $table->id();
        $table->string('make');
        $table->string('model');
        $table->timestamps();
    });
}

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.

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Car extends Model
{
    use HasFactory;

    protected $fillable = [
        'make', 'model',
    ];
}

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.

return [
    'make' => $this->faker->word(),
    'model' => $this->faker->word(),
];

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

C:\xampp\htdocs\laravel-test.com>php artisan tinker
Psy Shell v0.10.8 (PHP 7.4.19 — cli) by Justin Hileman
>>> Car::factory()->count(3)->create();
[!] Aliasing 'Car' to 'App\Models\Car' for this Tinker session.
=> Illuminate\Database\Eloquent\Collection {#3487
     all: [
       App\Models\Car {#3490
         make: "enim",
         model: "qui",
         updated_at: "2021-08-30 08:52:08",
         created_at: "2021-08-30 08:52:08",
         id: 1,
       },
       App\Models\Car {#3491
         make: "recusandae",
         model: "numquam",
         updated_at: "2021-08-30 08:52:08",
         created_at: "2021-08-30 08:52:08",
         id: 2,
       },
       App\Models\Car {#3492
         make: "maiores",
         model: "sequi",
         updated_at: "2021-08-30 08:52:08",
         created_at: "2021-08-30 08:52:08",
         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.

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

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.

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'password' => Hash::make('password'),
        ]);
    }
}

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.

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        User::factory()->count(10)->create();
    }
}

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
namespace Database\Seeders;

use App\Models\Car;
use Illuminate\Database\Seeder;

class CarSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Car::factory()->count(50)->create();
    }
}

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).

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // \App\Models\User::factory(10)->create();
    }
}

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.

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            UserSeeder::class,
            CarSeeder::class,
        ]);
    }
}

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

C:\xampp\htdocs\laravel-test.com>php artisan db:seed
Seeding: Database\Seeders\UserSeeder
Seeded:  Database\Seeders\UserSeeder (83.09ms)
Seeding: Database\Seeders\CarSeeder
Seeded:  Database\Seeders\CarSeeder (262.17ms)
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