[DoctrineBridge] Optimize fetching of entities to use WHERE IN and fix other inefficencies.
This commit is contained in:
parent
517eebcb31
commit
b919d92b52
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -19,4 +19,9 @@ class SingleIdentEntity
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->id;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user