Adding dummy data via a custom faker shell to our store
The excellent Jad Bittar added support for Faker to the Cake3 ORM as a plugin, so we can use this to generate dummy data for our application. This will allow us to easily test stuff going forward. Let’s start by installing the plugin:
composer require gourmet/faker
This will pull in both the CakePHP plugin as well as the Faker library. Next, lets generate a shell to generate dummy data:
cd /vagrant/app
# generate a dummy data shell
bin/cake bake shell DummyData
The new shell will be created in app/src/Shell/DummyDataShell.php
. It has a main
method which you can modify, and if you run the following command now:
bin/cake dummy_data
You’ll have the following - pretty plain - output:
vagrant@precise32:/vagrant/app$ bin/cake dummy_data
Welcome to CakePHP v3.0.0-beta3 Console
---------------------------------------------------------------
App : src
Path: /vagrant/app/src/
---------------------------------------------------------------
Lets actually do something with this new shell. In our DummyDataShell::main()
method, we’ll need to create a faker
object
$faker = \Faker\Factory::create();
Faker uses providers to give custom data types to fields. We’ll first populate the users
table, and to do so, we’ll need to provide fake email addresses. To do so, we’ll need to add the Internet
provider:
$faker->addProvider(new \Faker\Provider\Internet($faker));
To populate a specific type of entity, we need to create an EntityPopulator object. The Faker library provides a custom populator for the CakePHP framework, which we’ll leverage in our case. You simply need to provide the name of the table class:
$entityPopulator = new \Faker\ORM\CakePHP\EntityPopulator('Users');
Finally, we need to create a populator object that will actually insert data into the database. We need to pass in our EntityPopulator object, a number of records to insert, as well as custom formatters. The formatters come from providers - we added the Internet
provider above - or your own text. Faker tries to autodetect data types, but will default to stuff like plaintext
for email
fields, so we need to override this:
$populator = new \Faker\ORM\CakePHP\Populator($faker);
$populator->addEntity($entityPopulator, 20, [
'email' => function () use ($faker) { return $faker->email(); },
'password' => 'password',
]);
The last thing is to actually populate our table!
$populator->execute(['validate' => false]);
The full code sample will look like the following:
$this->out("Creating user populator");
$faker = \Faker\Factory::create();
$faker->addProvider(new \Faker\Provider\Internet($faker));
$entityPopulator = new \Faker\ORM\CakePHP\EntityPopulator('Users');
$populator = new \Faker\ORM\CakePHP\Populator($faker);
$populator->addEntity($entityPopulator, 20, [
'email' => function () use ($faker) { return $faker->email(); },
'password' => 'password',
]);
$this->out("Inserting");
$populator->execute(['validate' => false]);
I’ve added some calls to
$this->out()
to provide feedback in my shell. You can omit these or add more as you like. This is a special helper method available in shells
If you run this, you’ll recieve the following output:
vagrant@precise32:/vagrant/app$ bin/cake dummy_data
Welcome to CakePHP v3.0.0-beta3 Console
---------------------------------------------------------------
App : src
Path: /vagrant/app/src/
---------------------------------------------------------------
Creating user populator
Inserting
But more importantly, you’ll have 20 beautiful user records with passwords. You should be able to login as any of these users.
Homework time!
If you thought you’d get off this week, you thought incorrectly. Your homework is to create dummy data for every model we have in our app - a store without products is kind of useless. You can ignore the Orders
and OrderItems
models.