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.
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.
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:
... 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.