[DoctrineBridge] Optimize fetching of entities to use WHERE IN and fix other inefficencies.

This commit is contained in:
Benjamin Eberlei 2011-11-26 17:59:47 +01:00 committed by Christophe Coevoet
parent 517eebcb31
commit b919d92b52
4 changed files with 44 additions and 40 deletions

View File

@ -107,6 +107,9 @@ class EntityChoiceList extends ArrayChoiceList
// displaying entities as strings
if ($property) {
$this->propertyPath = new PropertyPath($property);
} else if (!method_exists($this->class, '__toString')) {
// Otherwise expect a __toString() method in the entity
throw new FormException('Entities passed to the choice field must have a "__toString()" method defined (or you can also override the "property" option).');
}
if (!is_array($choices) && !$choices instanceof \Closure && !is_null($choices)) {
@ -202,11 +205,6 @@ class EntityChoiceList extends ArrayChoiceList
// If the property option was given, use it
$value = $this->propertyPath->getValue($entity);
} else {
// Otherwise expect a __toString() method in the entity
if (!method_exists($entity, '__toString')) {
throw new FormException('Entities passed to the choice field must have a "__toString()" method defined (or you can also override the "property" option).');
}
$value = (string) $entity;
}
@ -261,7 +259,7 @@ class EntityChoiceList extends ArrayChoiceList
}
/**
* Returns the entity for the given key.
* Returns the entities for the given keys.
*
* If the underlying entities have composite identifiers, the choices
* are initialized. The key is expected to be the index in the choices
@ -270,35 +268,42 @@ class EntityChoiceList extends ArrayChoiceList
* If they have single identifiers, they are either fetched from the
* internal entity cache (if filled) or loaded from the database.
*
* @param string $key The choice key (for entities with composite
* identifiers) or entity ID (for entities with single
* identifiers)
*
* @return object The matching entity
* @param array $keys The choice key (for entities with composite
* identifiers) or entity ID (for entities with single
* identifiers)
* @return object[] The matching entity
*/
public function getEntity($key)
public function getEntitiesByKeys($keys)
{
if (!$this->loaded) {
$this->load();
}
try {
if (count($this->identifier) > 1) {
// $key is a collection index
$entities = $this->getEntities();
$found = array();
return isset($entities[$key]) ? $entities[$key] : null;
} elseif ($this->entities) {
return isset($this->entities[$key]) ? $this->entities[$key] : null;
} else if ($entityLoader = $this->entityLoader) {
$entities = $entityLoader->getEntitiesByKeys($this->identifier, array($key));
return (isset($entities[0])) ? $entities[0] : false;
if (count($this->identifier) > 1) {
// $key is a collection index
$entities = $this->getEntities();
foreach ($keys as $key) {
if (isset($entities[$key])) {
$found[] = $entities[$key];
}
}
return $this->em->find($this->class, $key);
} catch (NoResultException $e) {
return null;
} else if ($this->entities) {
foreach ($keys as $key) {
if (isset($this->entities[$key])) {
$found[] = $this->entities[$key];
}
}
} else if ($entityLoader = $this->entityLoader) {
$found = $entityLoader->getEntitiesByKeys($this->identifier, $keys);
} else if ($keys) {
$identifier = current($this->identifier);
$found = $this->em->getRepository($this->class)
->findBy(array($identifier => $keys));
}
return $found;
}
/**

View File

@ -84,19 +84,13 @@ class EntitiesToArrayTransformer implements DataTransformerInterface
throw new UnexpectedTypeException($keys, 'array');
}
$notFound = array();
// optimize this into a SELECT WHERE IN query
foreach ($keys as $key) {
if ($entity = $this->choiceList->getEntity($key)) {
$collection->add($entity);
} else {
$notFound[] = $key;
}
$entities = $this->choiceList->getEntitiesByKeys($keys);
if (count($keys) != count($entities)) {
throw new TransformationFailedException('Not all entities matching the keys were found.');
}
if (count($notFound) > 0) {
throw new TransformationFailedException(sprintf('The entities with keys "%s" could not be found', implode('", "', $notFound)));
foreach ($entities as $entity) {
$collection->add($entity);
}
return $collection;

View File

@ -74,10 +74,10 @@ class EntityToIdTransformer implements DataTransformerInterface
throw new UnexpectedTypeException($key, 'numeric');
}
if (!($entity = $this->choiceList->getEntity($key))) {
if (!($entities = $this->choiceList->getEntitiesByKeys(array($key)))) {
throw new TransformationFailedException(sprintf('The entity with key "%s" could not be found', $key));
}
return $entity;
return $entities[0];
}
}

View File

@ -19,4 +19,9 @@ class SingleIdentEntity
$this->id = $id;
$this->name = $name;
}
public function __toString()
{
return (string)$this->id;
}
}