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.
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.
Enhancing Laravel Data with Faker: Realistic Testing Made Easy
Elevate your Laravel testing with Faker for realistic data generation. Streamline development with dynamic, believable test data.
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 Seeders: Planting the Seeds of Your Database
Discover Laravel seeders for efficient database population. Learn to seed your database with data for development, testing, or staging.