diff --git a/lib/Doctrine/ORM/EntityManager.php b/lib/Doctrine/ORM/EntityManager.php index f09bacb89..9033c178c 100644 --- a/lib/Doctrine/ORM/EntityManager.php +++ b/lib/Doctrine/ORM/EntityManager.php @@ -368,28 +368,38 @@ class EntityManager implements ObjectManager * without actually loading it, if the entity is not yet loaded. * * @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. */ - public function getReference($entityName, $identifier) + public function getReference($entityName, $id) { $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. - if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) { + if ($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) { return ($entity instanceof $class->name) ? $entity : null; } if ($class->subClasses) { - return $this->find($entityName, $identifier); + return $this->find($entityName, $sortedId); } - if ( ! is_array($identifier)) { - $identifier = array($class->identifier[0] => $identifier); + if ( ! is_array($sortedId)) { + $sortedId = array($class->identifier[0] => $sortedId); } - $entity = $this->proxyFactory->getProxy($class->name, $identifier); - $this->unitOfWork->registerManaged($entity, $identifier, array()); + $entity = $this->proxyFactory->getProxy($class->name, $sortedId); + $this->unitOfWork->registerManaged($entity, $sortedId, array()); return $entity; } diff --git a/lib/Doctrine/ORM/EntityRepository.php b/lib/Doctrine/ORM/EntityRepository.php index f74448141..3261d7e61 100644 --- a/lib/Doctrine/ORM/EntityRepository.php +++ b/lib/Doctrine/ORM/EntityRepository.php @@ -107,8 +107,19 @@ class EntityRepository implements ObjectRepository */ 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 - 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)) { return null; } @@ -120,22 +131,16 @@ class EntityRepository implements ObjectRepository 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) { case LockMode::NONE: - return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id); + return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($sortedId); case LockMode::OPTIMISTIC: if ( ! $this->_class->isVersioned) { 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); @@ -146,7 +151,7 @@ class EntityRepository implements ObjectRepository 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); } } diff --git a/lib/Doctrine/ORM/ORMException.php b/lib/Doctrine/ORM/ORMException.php index f15e0fbe1..0e36217d9 100644 --- a/lib/Doctrine/ORM/ORMException.php +++ b/lib/Doctrine/ORM/ORMException.php @@ -144,4 +144,9 @@ class ORMException extends Exception return new self("Invalid repository class '".$className."'. ". "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); + } } diff --git a/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php b/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php index ee762d345..15f7e0bda 100644 --- a/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php @@ -92,4 +92,10 @@ class CompositePrimaryKeyTest extends \Doctrine\Tests\OrmFunctionalTestCase $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)); + } } \ No newline at end of file