Skip to content

Instantly share code, notes, and snippets.

@evillemez
Created April 4, 2014 17:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evillemez/9979385 to your computer and use it in GitHub Desktop.
Save evillemez/9979385 to your computer and use it in GitHub Desktop.
Brainstorming for a very small fixture generation library.
<?php
namespace AC\Fixtures;
/**
* Factories use Definitions and Pools to create and store (not persist) object instances.
*/
interface Factory
{
public function define($name); //create and returns Definition
public function getDefinition($name); //return definition
public function pool($number, $name); //define a pool of objects
public function populate(); //populate objects for defined pools
public function fetchOne($name, $comparator = null); //fetch from pool
public function fetchMultiple($num, $name, $comparator = null, $unique = true); //fetch multiple from pool, optionally pass matcher
public function fetchOneRandom($name); //fetch from pool
public function fetchMultipleRandom($num, $name, $unique = true); //fetch multiple from pool
public function fetchMatching($name, array $fields); //fetch multiple from pool
public function fetchAll($name); //fetch all
//one off creation of objects (not stored internally in pools, thus not fetchable directly)
public function generateOne($name, $args = null); //create one instance, not pooled
public function generate($num, $name, $args = null); //create multiple, not pooled
}
/**
* Defines creation of instances of a class.
*/
interface Definition
{
public function __construct($className);
public function setFactory(Factory $factory); //factory, if defined, is passed to callables
public function constructor($callable); //custom constructor, returns object instance
public function build($callable); //called after constructor
public function property($name, $callableOrValue); //set property generator
public function properties(array $map); //set multiple property generators
public function then($callable); //register a callable to be called after properties
public function generateOne($args = null); //instantiate and return 1 object
public function generate($num, $args = null); //instantiate and return multiple
}
/**
* Manages instances of objects created by Definitions
*/
interface Pool
{
public function __construct($num, Definition $def = null);
public function setNumber($num);
public function setDefinition(Definition $def);
public function populate($rebuild = false);
public function then($callable);
//calling a fetch method triggers "populate()"
public function fetchOne();
public function fetchOneRandom();
public function fetchMultiple($num, $comparator = null, $unique = true);
public function fetchMultipleRandom($num, $unique = true);
public function fetchMatching($comparator, $limit = null);
public function fetchMatchingFields(array $propertyComparators, $limit = null);
}
//stuff to use when creating
$f = new Faker();
$em = new DoctrineEntityManager();
$batchPersist = function($objs) use ($em) { foreach ($objs as $obj) { $em->persist($obj); } $em->flush(); };
//create factory and define pools
$factory = new Factory();
$factory->pool(100, "Hammerspace\ModelBundle\Entity\AO")->then($batchPersist);
$factory->pool(30, "Hammerspace\ModelBundle\Entity\Section")->then($batchPersist);
$factory->pool(20, "Hammerspace\ModelBundle\Entity\Form")->then($batchPersist);
$factory->pool(10, "Hammerspace\ModelBundle\Entity\Exam")->then($batchPersist);
$factory->define('Hammerspace\ModelBundle\Entity\AO')
->properties([
'name' => function () use ($faker) { return $f->words(3); },
'instructions' => function () use ($faker) { return $f->sentence(15); },
'type' => function () use ($faker) { return $f->randomElement(['mc','cr']); },
])
->then(function($ao, $factory) {
if ('mc' == $ao->getType()) $items = $factory->generate(rand(1, 4), 'Hammerspace\ModelBundle\Entity\ItemMC', $ao);
if ('cr' == $ao->getType()) $items = $factory->generate(rand(1, 4), 'Hammerspace\ModelBundle\Entity\ItemCR', $ao);
//relies on model behavior to properly set "sequence"
$ao->addItems($items);
})
;
$processBaseItem = function($item, $factory, $ao) {
//...
$item->setUic();
//...
};
$factory->define('Hammerspace\ModelBundle\Entity\ItemMC')->properties([
//... set some fields
])
->then(function ($item, $factory) { $item->addOptions($factory->generate(4, 'Hammerspace\ModelBundle\Entity\ItemMCOption')); })
->then($processBaseItem);
$factory->define('Hammerspace\ModelBundle\Entity\ItemCR')
->properties([
//set some fields directly
])
->then(function($item) {
//do ItemCR specific stuff
})
->then($processBaseItem);
$factory->populate(); //populates all defined pools, which may trigger persisting things, if set to do so
$adminDate = $factory->fetchOne('Hammerspace\ModelBundle\Entity\Exam')->getAdmins()[0]->getDates()[0];
//not defined in pools, throw exceptions:
$obj = $factory->fetchOne('Hammerspace\ModelBundle\Entity\AdminDate');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment