1
0
Fork 0
mirror of synced 2025-04-03 13:23:37 +03:00

DDC-1517 - Fix EntityRepository#find() and EntityManager#getReference() breaking on invalid or missing identifiers.

This commit is contained in:
Benjamin Eberlei 2011-12-01 21:18:39 +01:00
parent 5e3e8b3957
commit 619a31913a
4 changed files with 44 additions and 18 deletions

View file

@ -368,28 +368,38 @@ class EntityManager implements ObjectManager
* without actually loading it, if the entity is not yet loaded. * without actually loading it, if the entity is not yet loaded.
* *
* @param string $entityName The name of the entity type. * @param string $entityName The name of the entity type.
* @param mixed $identifier The entity identifier. * @param mixed $id The entity identifier.
* @return object The entity reference. * @return object The entity reference.
*/ */
public function getReference($entityName, $identifier) public function getReference($entityName, $id)
{ {
$class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
if ( ! is_array($id)) {
$id = array($class->identifier[0] => $id);
}
$sortedId = array();
foreach ($class->identifier as $identifier) {
if (!isset($id[$identifier])) {
throw ORMException::missingIdentifierField($class->name, $identifier);
}
$sortedId[$identifier] = $id[$identifier];
}
// Check identity map first, if its already in there just return it. // Check identity map first, if its already in there just return it.
if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) { if ($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) {
return ($entity instanceof $class->name) ? $entity : null; return ($entity instanceof $class->name) ? $entity : null;
} }
if ($class->subClasses) { if ($class->subClasses) {
return $this->find($entityName, $identifier); return $this->find($entityName, $sortedId);
} }
if ( ! is_array($identifier)) { if ( ! is_array($sortedId)) {
$identifier = array($class->identifier[0] => $identifier); $sortedId = array($class->identifier[0] => $sortedId);
} }
$entity = $this->proxyFactory->getProxy($class->name, $identifier); $entity = $this->proxyFactory->getProxy($class->name, $sortedId);
$this->unitOfWork->registerManaged($entity, $identifier, array()); $this->unitOfWork->registerManaged($entity, $sortedId, array());
return $entity; return $entity;
} }

View file

@ -107,8 +107,19 @@ class EntityRepository implements ObjectRepository
*/ */
public function find($id, $lockMode = LockMode::NONE, $lockVersion = null) public function find($id, $lockMode = LockMode::NONE, $lockVersion = null)
{ {
if ( ! is_array($id)) {
$id = array($this->_class->identifier[0] => $id);
}
$sortedId = array();
foreach ($this->_class->identifier as $identifier) {
if (!isset($id[$identifier])) {
throw ORMException::missingIdentifierField($this->_class->name, $identifier);
}
$sortedId[$identifier] = $id[$identifier];
}
// Check identity map first // Check identity map first
if ($entity = $this->_em->getUnitOfWork()->tryGetById($id, $this->_class->rootEntityName)) { if ($entity = $this->_em->getUnitOfWork()->tryGetById($sortedId, $this->_class->rootEntityName)) {
if ( ! ($entity instanceof $this->_class->name)) { if ( ! ($entity instanceof $this->_class->name)) {
return null; return null;
} }
@ -120,22 +131,16 @@ class EntityRepository implements ObjectRepository
return $entity; // Hit! return $entity; // Hit!
} }
if ( ! is_array($id) || count($id) <= 1) {
// @todo FIXME: Not correct. Relies on specific order.
$value = is_array($id) ? array_values($id) : array($id);
$id = array_combine($this->_class->identifier, $value);
}
switch ($lockMode) { switch ($lockMode) {
case LockMode::NONE: case LockMode::NONE:
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id); return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($sortedId);
case LockMode::OPTIMISTIC: case LockMode::OPTIMISTIC:
if ( ! $this->_class->isVersioned) { if ( ! $this->_class->isVersioned) {
throw OptimisticLockException::notVersioned($this->_entityName); throw OptimisticLockException::notVersioned($this->_entityName);
} }
$entity = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id); $entity = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($sortedId);
$this->_em->getUnitOfWork()->lock($entity, $lockMode, $lockVersion); $this->_em->getUnitOfWork()->lock($entity, $lockMode, $lockVersion);
@ -146,7 +151,7 @@ class EntityRepository implements ObjectRepository
throw TransactionRequiredException::transactionRequired(); throw TransactionRequiredException::transactionRequired();
} }
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id, null, null, array(), $lockMode); return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($sortedId, null, null, array(), $lockMode);
} }
} }

View file

@ -144,4 +144,9 @@ class ORMException extends Exception
return new self("Invalid repository class '".$className."'. ". return new self("Invalid repository class '".$className."'. ".
"it must be a Doctrine\ORM\EntityRepository."); "it must be a Doctrine\ORM\EntityRepository.");
} }
public static function missingIdentifierField($className, $fieldName)
{
return new self("The identifier $fieldName is missing for a query of " . $className);
}
} }

View file

@ -92,4 +92,10 @@ class CompositePrimaryKeyTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(1, count($tours)); $this->assertEquals(1, count($tours));
} }
public function testSpecifiyUnknownIdentifierPrimaryKeyFails()
{
$this->setExpectedException('Doctrine\ORM\ORMException', 'The identifier long is missing for a query of Doctrine\Tests\Models\Navigation\NavPointOfInterest');
$poi = $this->_em->find('Doctrine\Tests\Models\Navigation\NavPointOfInterest', array('key1' => 100));
}
} }