Search code examples
laraveleloquentlaravel-seeding

the convention for persisting fake data to the database


I want to create a bunch of fake data for my app for testing, I read this stackoverflow answer and it seems that factories are what people use for fake data.

I read through the Laravel docs and it seems that seeders have a built in artisan command to seed the Database, while factories don't. for factories I either have to:

  1. add User::factory()->create(); somewhere in my codebase to persist fake data in the DB and later remove it
  2. manually create an artisan command that runs User::factory()->create(); under the hood

both seem to me like something the Laravel community won't settle for, so I am here asking what the solution is and if in my case I should switch to a seeder.


Solution

  • To fill the database with test data, seeding is used.

    php artisan db:seed
    OR
    php artisan db:seed --class=ClassName
    

    But to generate your test data you need factories that are related to your models.

    To generate a new factory, use the make:factory Artisan command:

    php artisan make:factory UserFactory
    

    This command will place the new factory class in the database/factories directory of your application and specify the path to the model

    namespace Database\Factories;
    
    use Illuminate\Database\Eloquent\Factories\Factory;
    use Illuminate\Support\Str;
    
    class UserFactory extends Factory
    {
        protected $model = User::class;
    
        /**
         * Define the default state of the model.
         *
         * @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),
            ];
        }
    }
    

    Once you have defined your factories, you can use the static factory method provided to your models by the Illuminate\Database\Eloquent\Factories\HasFactory trait to create a factory instance for that model.

    class User extends Model
    {
       use HasFactory;
    }
    

    The factory method of the HasFactory trait will use conventions to determine the appropriate factory for the model. Specifically, the method will look for a factory in the Database\Factories namespace whose class name matches the model name and has the Factory suffix.

    Seeder + Factory

    class DatabaseSeeder extends Seeder
    {
    
       public function run()
       {
            User::factory()->create();
            
            // Override attributes
            $user = User::factory()->create([
               'name' => 'Abigail',
            ]);
       }
    }