1
0
mirror of https://github.com/fzaninotto/Faker.git synced 2025-03-22 00:09:59 +01:00

Improved Doctrine populator

* it now enables to call methods on entity wit generated arguments
* added posibility of creating unique ids if they are not auto generated
* added posibility to load more entities with one-to-one relationship
This commit is contained in:
Miloslav Nenadal 2013-01-29 11:20:20 +01:00
parent 6d051d4c6c
commit 82f2555145
2 changed files with 94 additions and 12 deletions

View File

@ -17,6 +17,10 @@ class EntityPopulator
* @var array
*/
protected $columnFormatters = array();
/**
* @var array
*/
protected $modifiers = array();
/**
* Class constructor.
@ -51,6 +55,21 @@ class EntityPopulator
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters);
}
public function setModifiers(array $modifiers)
{
$this->modifiers = $modifiers;
}
public function getModifiers()
{
return $this->modifiers;
}
public function mergeModifiersWith(array $modifiers)
{
$this->modifiers = array_merge($this->modifiers, $modifiers);
}
public function guessColumnFormatters(\Faker\Generator $generator)
{
$formatters = array();
@ -78,7 +97,27 @@ class EntityPopulator
}
$relatedClass = $this->class->getAssociationTargetClass($assocName);
$formatters[$assocName] = function($inserted) use ($relatedClass) { return isset($inserted[$relatedClass]) ? $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)] : null; };
$unique = false;
$mappings = $this->class->getAssociationMappings();
foreach ($mappings as $mapping) {
if ($mapping['targetEntity'] == $relatedClass) {
if ($mapping['type'] == ClassMetadata::ONE_TO_ONE) {
$unique = true;
break;
}
}
}
$index = 0;
$formatters[$assocName] = function($inserted) use ($relatedClass, &$index, $unique) {
if ($unique && isset($inserted[$relatedClass])) {
return $inserted[$relatedClass][$index++];
} else if (isset($inserted[$relatedClass])) {
return $inserted[$relatedClass][mt_rand(0, count($inserted[$relatedClass]) - 1)];
}
return null;
};
}
return $formatters;
@ -87,18 +126,18 @@ class EntityPopulator
/**
* Insert one new record using the Entity class.
*/
public function execute($manager, $insertedEntities)
public function execute($manager, $insertedEntities, $generateId = false)
{
$obj = $this->class->newInstance();
foreach ($this->columnFormatters as $field => $format) {
if (null !== $format) {
$value = is_callable($format) ? $format($insertedEntities, $obj) : $format;
if (is_callable(array($obj, $field))) {
$obj->$field($value);
} else {
$this->class->reflFields[$field]->setValue($obj, $value);
}
$this->fillColumns($obj, $insertedEntities);
$this->callMethods($obj, $insertedEntities);
if ($generateId) {
$idsName = $this->class->getIdentifier();
foreach ($idsName as $idName) {
$id = $this->generateId($obj, $idName, $manager);
$this->class->reflFields[$idName]->setValue($obj, $id);
}
}
@ -107,4 +146,42 @@ class EntityPopulator
return $obj;
}
private function fillColumns($obj, $insertedEntities)
{
foreach ($this->columnFormatters as $field => $format) {
if (null !== $format) {
$value = is_callable($format) ? $format($insertedEntities, $obj) : $format;
$this->class->reflFields[$field]->setValue($obj, $value);
}
}
}
private function callMethods($obj, $insertedEntities)
{
foreach ($this->getModifiers() as $method => $formats) {
$args = array();
foreach ($formats as $format) {
$args[] = is_callable($format) ? $format($insertedEntities, $obj) : $format;
}
call_user_func_array(array($obj, $method), $args);
}
}
private function generateId($obj, $column, $manager)
{
/* @var $repository \Doctrine\ORM\EntityRepository */
$repository = $manager->getRepository(get_class($obj));
$result = $repository->createQueryBuilder('e')
->select(sprintf('e.%s', $column))
->getQuery()
->getResult();
$ids = array_map('current', $result);
$id = null;
do {
$id = rand();
} while(in_array($id, $ids));
return $id;
}
}

View File

@ -14,6 +14,7 @@ class Populator
protected $manager;
protected $entities = array();
protected $quantities = array();
protected $generateId = array();
public function __construct(\Faker\Generator $generator, ObjectManager $manager = null)
{
@ -27,7 +28,7 @@ class Populator
* @param mixed $entity A Doctrine classname, or a \Faker\ORM\Doctrine\EntityPopulator instance
* @param int $number The number of entities to populate
*/
public function addEntity($entity, $number, $customColumnFormatters = array())
public function addEntity($entity, $number, $customColumnFormatters = array(), $customModifiers = array(), $generateId = false)
{
if (!$entity instanceof \Faker\ORM\Doctrine\EntityPopulator) {
$entity = new \Faker\ORM\Doctrine\EntityPopulator($this->manager->getClassMetadata($entity));
@ -36,6 +37,9 @@ class Populator
if ($customColumnFormatters) {
$entity->mergeColumnFormattersWith($customColumnFormatters);
}
$entity->mergeModifiersWith($customModifiers);
$this->generateId[$entity->getClass()] = $generateId;
$class = $entity->getClass();
$this->entities[$class] = $entity;
$this->quantities[$class] = $number;
@ -59,8 +63,9 @@ class Populator
$insertedEntities = array();
foreach ($this->quantities as $class => $number) {
$generateId = $this->generateId[$class];
for ($i=0; $i < $number; $i++) {
$insertedEntities[$class][]= $this->entities[$class]->execute($entityManager, $insertedEntities);
$insertedEntities[$class][]= $this->entities[$class]->execute($entityManager, $insertedEntities, $generateId);
}
$entityManager->flush();
}