Laravel — P32: Factory with Faker

The Ultimate Laravel Pair: Factories and Faker for Dynamic Data

For the last two articles, we went through an introduction of the Faker library and the Factory concept in Laravel. We worked on the User model, which was already created for us, but we haven’t looked at actually creating our own Factory.

Laravel — P31: Faker

To create a Factory, we first need to create a model. We’ll create a new model and factory at the same time.

# php artisan make:model Car -mf

   INFO  Model [app/Models/Car.php] created successfully.  

   INFO  Factory [database/factories/CarFactory.php] created successfully.  

   INFO  Migration [database/migrations/2023_01_16_162646_create_cars_table.php] created successfully.  

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

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cars', function (Blueprint $table) {
            $table->id();
            $table->string('make');
            $table->string('model');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('cars');
    }
};

Run the migration.

# php artisan migrate

   INFO  Running migrations.  

  2023_01_16_162646_create_cars_table .................................................. 24ms DONE

# 

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.

<?php

namespace App\Models;

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

class Car extends Model
{
    use HasFactory;

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

We haven’t looked at the $fillable property just yet, and we will when we get to forms. If we don’t set this property, Laravel will reject our ability to insert data into the make and model fields.

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

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Car>
 */
class CarFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            //
        ];
    }
}

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.

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Car>
 */
class CarFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        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.

# php artisan tinker

Psy Shell v0.11.9 (PHP 8.1.13 — cli) by Justin Hileman
> Car::factory()->count(3)->create();
[!] Aliasing 'Car' to 'App\Models\Car' for this Tinker session.
= Illuminate\Database\Eloquent\Collection {#3800
    all: [
      App\Models\Car {#3804
        make: "hic",
        model: "et",
        updated_at: "2023-01-16 16:34:13",
        created_at: "2023-01-16 16:34:13",
        id: 1,
      },
      App\Models\Car {#3802
        make: "quo",
        model: "voluptatem",
        updated_at: "2023-01-16 16:34:13",
        created_at: "2023-01-16 16:34:13",
        id: 2,
      },
      App\Models\Car {#3805
        make: "voluptatem",
        model: "reiciendis",
        updated_at: "2023-01-16 16:34:13",
        created_at: "2023-01-16 16:34:13",
        id: 3,
      },
    ],
  }

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

mysql> select * from cars;
+----+------------+------------+---------------------+---------------------+
| id | make       | model      | created_at          | updated_at          |
+----+------------+------------+---------------------+---------------------+
|  1 | hic        | et         | 2023-01-16 16:34:13 | 2023-01-16 16:34:13 |
|  2 | quo        | voluptatem | 2023-01-16 16:34:13 | 2023-01-16 16:34:13 |
|  3 | voluptatem | reiciendis | 2023-01-16 16:34:13 | 2023-01-16 16:34:13 |
+----+------------+------------+---------------------+---------------------+
3 rows in set (0.00 sec)

mysql> 

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

In previous version of Laravel, you had to specify the --model=Car flag, where 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. With Laravel 9.x, you don’t have to do that anymore since Laravel looks for factories in a specific namespace, Database\Factories and looks for a factory that’s named like the model with the word Factory appended to it, i.e. CarFactory.

Also verify that the trait, HasFactory is included in your model. If it’s not, you’ll need to specify that

<?php

namespace App\Models;

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

class Car extends Model
{
    use HasFactory;

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

Now that we know how to create Factories, use Faker data to create new data, and populate it into the database with tinker, we’re ready for seeders, which helps eliminate our need for tinker and automates the insertion process.

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.

https://github.com/dinocajic/youtube-laravel?source=post_page—–8815d9f52fa0

Laravel Series

Continue your Laravel Learning.

Laravel — P31- Faker

Enhancing Laravel Data with Faker: Realistic Testing Made Easy

Laravel – P31: Faker Library

Elevate your Laravel testing with Faker for realistic data generation. Streamline development with dynamic, believable test data.

Laravel — P32: Factory with Faker

The Ultimate Laravel Pair: Factories and Faker for Dynamic Data

Laravel – P32: Factory With Faker

Combine Laravel factories with Faker for unparalleled testing data. Create dynamic, realistic environments for development & testing.

Laravel — P33: Seeders

Laravel Seeders: Planting the Seeds of Your Database

Laravel – P33: Seeders

Discover Laravel seeders for efficient database population. Learn to seed your database with data for development, testing, or staging.

Leave a Reply