diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 8f82aa96f..0294b9f82 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -49,6 +49,7 @@ use Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister; use Doctrine\ORM\Persisters\Collection\OneToManyPersister; use Doctrine\ORM\Persisters\Collection\ManyToManyPersister; use Doctrine\ORM\Utility\IdentifierFlattener; +use Doctrine\ORM\Cache\AssociationCacheEntry; /** * The UnitOfWork is responsible for tracking changes to objects during an @@ -2490,22 +2491,7 @@ class UnitOfWork implements PropertyChangedListener $class = $this->em->getClassMetadata($className); //$isReadOnly = isset($hints[Query::HINT_READ_ONLY]); - if ($class->isIdentifierComposite) { - $id = array(); - - foreach ($class->identifier as $fieldName) { - $id[$fieldName] = isset($class->associationMappings[$fieldName]) - ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] - : $data[$fieldName]; - } - } else { - $id = isset($class->associationMappings[$class->identifier[0]]) - ? $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']] - : $data[$class->identifier[0]]; - - $id = array($class->identifier[0] => $id); - } - + $id = $this->identifierFlattener->flattenIdentifier($class, $data); $idHash = implode(' ', $id); if (isset($this->identityMap[$class->rootEntityName][$idHash])) { @@ -2639,10 +2625,18 @@ class UnitOfWork implements PropertyChangedListener if ($joinColumnValue !== null) { if ($targetClass->containsForeignIdentifier) { + if ($joinColumnValue instanceof AssociationCacheEntry) { + $joinColumnValue = implode(' ', $joinColumnValue->identifier); + } + $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue; } else { $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue; } + } elseif ($targetClass->containsForeignIdentifier && in_array($targetClass->getFieldForColumn($targetColumn), $targetClass->identifier, true)) { + // the missing key is part of target's entity primary key + $associatedId = array(); + break; } } diff --git a/lib/Doctrine/ORM/Utility/IdentifierFlattener.php b/lib/Doctrine/ORM/Utility/IdentifierFlattener.php index 166e0acb6..fbad711e3 100644 --- a/lib/Doctrine/ORM/Utility/IdentifierFlattener.php +++ b/lib/Doctrine/ORM/Utility/IdentifierFlattener.php @@ -71,22 +71,24 @@ final class IdentifierFlattener { $flatId = array(); - foreach ($id as $idField => $idValue) { - if (isset($class->associationMappings[$idField]) && is_object($idValue)) { - /* @var $targetClassMetadata ClassMetadata */ + foreach ($class->identifier as $field) { + if (isset($class->associationMappings[$field]) && isset($id[$field]) && is_object($id[$field])) { $targetClassMetadata = $this->metadataFactory->getMetadataFor( - $class->associationMappings[$idField]['targetEntity'] + $class->associationMappings[$field]['targetEntity'] ); - - $associatedId = $this->unitOfWork->isInIdentityMap($idValue) - ? $this->unitOfWork->getEntityIdentifier($idValue) - : $targetClassMetadata->getIdentifierValues($idValue); - - $flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]]; + $associatedId = $this->flattenIdentifier($targetClassMetadata, $this->unitOfWork->getEntityIdentifier($id[$field])); + $flatId[$field] = implode(' ', $associatedId); + } elseif (isset($class->associationMappings[$field])) { + $associatedId = array(); + foreach ($class->associationMappings[$field]['joinColumns'] as $joinColumn) { + $associatedId[] = $id[$joinColumn['name']]; + } + $flatId[$field] = implode(' ', $associatedId); } else { - $flatId[$idField] = $idValue; + $flatId[$field] = $id[$field]; } } + return $flatId; } diff --git a/tests/Doctrine/Tests/ORM/Utility/IdentifierFlattenerTest.php b/tests/Doctrine/Tests/ORM/Utility/IdentifierFlattenerTest.php index 63536c886..dad6ce4b3 100644 --- a/tests/Doctrine/Tests/ORM/Utility/IdentifierFlattenerTest.php +++ b/tests/Doctrine/Tests/ORM/Utility/IdentifierFlattenerTest.php @@ -9,6 +9,7 @@ use Doctrine\Tests\Models\Cache\City; use Doctrine\Tests\Models\Cache\Flight; use Doctrine\ORM\ORMException; use Doctrine\ORM\Utility\IdentifierFlattener; + /** * Test the IdentifierFlattener utility class * @@ -87,7 +88,7 @@ class IdentifierFlattenerTest extends OrmFunctionalTestCase $this->assertArrayHasKey('secondEntity', $flatIds, 'It should be called secondEntity'); - $this->assertSame($id['secondEntity']->id, $flatIds['secondEntity']); + $this->assertEquals($id['secondEntity']->id, $flatIds['secondEntity']); } /** @@ -115,8 +116,8 @@ class IdentifierFlattenerTest extends OrmFunctionalTestCase $this->assertArrayHasKey('leavingFrom', $id); $this->assertArrayHasKey('goingTo', $id); - $this->assertSame($leeds, $id['leavingFrom']); - $this->assertSame($london, $id['goingTo']); + $this->assertEquals($leeds, $id['leavingFrom']); + $this->assertEquals($london, $id['goingTo']); $flatIds = $this->identifierFlattener->flattenIdentifier($class, $id); @@ -125,7 +126,7 @@ class IdentifierFlattenerTest extends OrmFunctionalTestCase $this->assertArrayHasKey('leavingFrom', $flatIds); $this->assertArrayHasKey('goingTo', $flatIds); - $this->assertSame($id['leavingFrom']->getId(), $flatIds['leavingFrom']); - $this->assertSame($id['goingTo']->getId(), $flatIds['goingTo']); + $this->assertEquals($id['leavingFrom']->getId(), $flatIds['leavingFrom']); + $this->assertEquals($id['goingTo']->getId(), $flatIds['goingTo']); } }