Laravel seeders and factories

Seeders and factories are useful for building up data, whether its fake or real and can also be used for visualising or testing data within your application.



Whats the difference between a seeder and a factory?

A seeder informs the application what needs building.

A factory is the structure of the data being seeded.


Why do I need them?

In truth, they aren't necessary for a lot of different web applications but learning how to use them makes test data easier to come by.

Say for example you have 3 database tables, contacts, companies and a linking table company_contacts.

You may want to use data to show relationships between company and contacts for demonstration purposes. So, without entering some contacts and companies and then linking them, a seeder would do the hard work for you.

Creating Laravel seeders and factories

To create a seeder in Laravel, run the following command: 





Example:

php artisan make:seeder ContactSeeder

This will place a new file in the database/seeders directory.

---

To create a factory in Laravel, run the following command:


Example:

php artisan make:factory ContactFactory 

This will place a new file in the database/factories directory

Seeding: The basics

The whole point of seeding is to instruct the system to fill in some data, whether its fixed or random. In Laravel, random is made easier with faker. Faker is a tool which allows you to generate real-ish data without any effort. Obviously in some circumstances you may be looking to fill in types database tables, in these instances, setting what goes in is preferable.

Lets delve into the two different types of seeder.

Seeding only seeder

The seeding only seeder uses the factory for that model created for the purpose of seeding. To create 50 items of a particular model within the seeder you would simply call the following:

Contact::factory(50)->create();

 Your seeder wouldnt look overly crammed and you would probably be thinking this is simple stuff at this point, you would probably be right. However, there more are important things to remember.

The first is that the model you are using MUST have the following line within the models class:

    use HasFactory;

The next thing to remember is that your factorys model should match the model as well. I recently ran into this issue where an error about App\Models\Model does not exist and this was simply because I had missed out the model declaration in the factory


So as a working example, this line should read:

protected $model = Contact::class;

Don't forget to remove the imported use statement for the incorrect Model class 

use App\Models\Model; //Remove this

 Lets move onto the factory for the contact now.

Its not that exciting in itself, you have a definition method which returns an array and that's about all you'll ever need (except the declared model variable line).


So what do we put here?

A key => value array of all the values you want to seed within your model.

Lets put this into context, the contact itself here is going to have 5 fillable fields:

  • First name
  • Last name
  • Country
  • Contact number
  • Email address
Initially filled in, this looks like:


We have no factory values yet, so lets use faker and add some values to our fields.
Note: Faker is now in an archived state. This does not mean that it is a redundant archive, unsafe to use or that it has been replaced.

Would you look at that, faker definitions were easily added for our fake data.

If I now go ahead and run the command for seeding, we would actually get nothing:

php artisan db:seed

This is because behind the scenes this is calling the DatabaseSeeder file in the seeders directory. Lets have a look at it:

 


Not too exciting but we can see it doesnt call our seeder! As you can see here, you dont need to define a seeder for every single seed you want to make but for good practice, it keeps the logic separate in case you need to do something different (such as the second type of seed which I will go into shortly).

I have changed the run method to call the contact seeder class, which in turn will run the seeders factories etc.


You can add multiple call lines or pass an array of seeder classes in here and they will be called in order of appearance within the array.

Lets run the seeder call now and we can see the process in seeding, seeded and completed states as it passes through:


If you want to call a single seeder however, this is possible to by levying the class argument

php artisan db:seed --class=ContactSeeder


Seeding data directly 

This is a much simpler way of seeding, however, its as complex as you want to make it. For this approach, we do not need a factory, just the seeder.

The table definition I am going to use this time will only use three fields as this is for a company and generally speaking, other tables can hold other company information.

  • name
  • location
  • vat_no
In our run definition in the CompanySeeder file, this time I am going to create a Company::create(); line for each manual seed I want to make.


This is literally it! Thats the data directly method. You can call the seeders in the same way as before:

php artisan db:seed
or
php artisan db:seed --class=CompanySeeder



Final note

You CAN be much more complex with definitions but if you want to use created data within the seeding process, you should create factory calls of 1 at a time in a loop. 

Useful commands

  • php artisan make:seeder <seeder name>
  • php artisan make:factory <factory name>
  • php artisan db:seed
  • php artisan db:seed --class=<class name seeder>
  • php artisan migrate
  • php artisan migrate:fresh --seed
  • php artisan make:model <model name>
    • You can add onto the end -r for resource, -m for migration -c for controller or -mcr for all of them at the same time

Resources:

Comments