Buy Access to Course
11.

Custom Alice Faker Function

Share this awesome video!

|

Keep on Learning!

The Faker name() function gives us a poor genus name. Yea, I know - this is just fake data - but it's so wrong that it fails at its one job: to give us some somewhat realistic data to make development easy.

Here's our goal: use a new <genus()> function in Alice and have this return the name of a random ocean-bound genus:

AppBundle\Entity\Genus:
genus_{1..10}:
name: <genus()>
// ... lines 4 - 7

This shouldn't work yet - but try it to see the error:

./bin/console doctrine:fixtures:load

Unknown formatter "genus"

Faker calls these functions "formatters". Can we create our own formatter? Absolutely.

Adding a Custom Formatter (Function)

In LoadFixtures, break the load() call onto multiple lines to keep things short and civilized. Now, add a third argument - it's sort of an "options" array. Give it a key called providers - these will be additional objects that provide formatter functions - and set it to an array with $this:

// ... lines 1 - 9
class LoadFixtures implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$objects = Fixtures::load(
__DIR__.'/fixtures.yml',
$manager,
[
'providers' => [$this]
]
);
}
// ... lines 22 - 45
}

And we're nearly done! To add a new genus formatter, add public function genus(). I've already prepared a lovely list of some fantastic genuses that live in the ocean:

// ... lines 1 - 9
class LoadFixtures implements FixtureInterface
{
// ... lines 12 - 22
public function genus()
{
$genera = [
'Octopus',
'Balaena',
'Orcinus',
'Hippocampus',
'Asterias',
'Amphiprion',
'Carcharodon',
'Aurelia',
'Cucumaria',
'Balistoides',
'Paralithodes',
'Chelonia',
'Trichechus',
'Eumetopias'
];
// ... lines 41 - 44
}
}

Finish this with $key = array_rand($genera) and then return $genera[$key]:

// ... lines 1 - 9
class LoadFixtures implements FixtureInterface
{
// ... lines 12 - 22
public function genus()
{
// ... lines 25 - 41
$key = array_rand($genera);
return $genera[$key];
}
}

Let's give it a try:

./bin/console doctrine:fixtures:load

No errors! Refresh! Ah, so much better.

New Random Boolean Column

Now, hold on, we have a new requirement: we need the ability to have published and unpublished genuses - for those times when we create a new genus, but we're still trying to think of a fun fact before it shows up on the site. With our beautiful migration and fixtures systems, this will be a breeze.

First, open Genus and add a new private property - call it $isPublished. Next, use the "Code"->"Generate" shortcut - or Ctrl+Enter - to generate the annotations:

95 lines | src/AppBundle/Entity/Genus.php
// ... lines 1 - 10
class Genus
{
// ... lines 13 - 39
/**
* @ORM\Column(type="boolean")
*/
private $isPublished = true;
// ... lines 44 - 89
public function setIsPublished($isPublished)
{
$this->isPublished = $isPublished;
}
}

Hey that was cool! Because the property started with is, PhpStorm correctly guessed that this is a boolean column. Go team!

At the bottom, generate just the setter function. We can add a getter function later... if we need one.

We need to update the fixtures. But first, find the command line and generate the migration:

./bin/console doctrine:migrations:diff

Be a responsible dev and make sure the migration looks right:

// ... lines 1 - 10
class Version20160207083347 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE genus ADD is_published TINYINT(1) NOT NULL');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE genus DROP is_published');
}
}

Actually, it looks perfect. Run it:

./bin/console doctrine:migrations:migrate

Last step: we want to have a few unpublished genuses in the random data set. Open the Faker documentation and search for "boolean". Perfect! There's a built-in boolean() function and we can control the $chanceOfGettingTrue. In the fixtures file, add isPublished and set that to boolean(75) - so that most genuses are published:

AppBundle\Entity\Genus:
genus_{1..10}:
// ... lines 3 - 6
isPublished: <boolean(75)>

Re-run the fixtures!

./bin/console doctrine:fixtures:load

Hey, no errors! Now, to only show the published genuses on the list page, we need a custom query.