diff --git a/lib/Doctrine/ORM/Exception/EntityIdentityCollisionException.php b/lib/Doctrine/ORM/Exception/EntityIdentityCollisionException.php new file mode 100644 index 00000000000..a70108c6f56 --- /dev/null +++ b/lib/Doctrine/ORM/Exception/EntityIdentityCollisionException.php @@ -0,0 +1,42 @@ +identityMap[$className][$idHash])) { if ($this->identityMap[$className][$idHash] !== $entity) { if ($this->em->getConfiguration()->isRejectIdCollisionInIdentityMapEnabled()) { - throw new RuntimeException( - sprintf( - <<<'EXCEPTION' -While adding an entity of class %s with an ID hash of "%s" to the identity map, -another object of class %s was already present for the same ID. This exception -is a safeguard against an internal inconsistency - IDs should uniquely map to -entity object instances. This problem may occur if: - -- you use application-provided IDs and reuse ID values; -- database-provided IDs are reassigned after truncating the database without - clearing the EntityManager; -- you might have been using EntityManager#getReference() to create a reference - for a nonexistent ID that was subsequently (by the RDBMS) assigned to another - entity. + throw EntityIdentityCollisionException::create($this->identityMap[$className][$idHash], $entity, $idHash); + } -Otherwise, it might be an ORM-internal inconsistency, please report it. -EXCEPTION - , - get_class($entity), - $idHash, - get_class($this->identityMap[$className][$idHash]) - ) - ); - } else { - Deprecation::trigger( - 'doctrine/orm', - 'https://github.com/doctrine/orm/pull/10785', - <<<'EXCEPTION' + Deprecation::trigger( + 'doctrine/orm', + 'https://github.com/doctrine/orm/pull/10785', + <<<'EXCEPTION' While adding an entity of class %s with an ID hash of "%s" to the identity map, another object of class %s was already present for the same ID. This will trigger an exception in ORM 3.0. @@ -1683,12 +1664,11 @@ public function addToIdentityMap($entity) \Doctrine\ORM\Configuration::setRejectIdCollisionInIdentityMap on the entity manager's configuration. EXCEPTION - , - get_class($entity), - $idHash, - get_class($this->identityMap[$className][$idHash]) - ); - } + , + get_class($entity), + $idHash, + get_class($this->identityMap[$className][$idHash]) + ); } return false; diff --git a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php index 2be3feba4ed..cfd60ab8cdc 100644 --- a/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php @@ -5,6 +5,7 @@ namespace Doctrine\Tests\ORM\Functional; use Doctrine\ORM\EntityNotFoundException; +use Doctrine\ORM\Exception\EntityIdentityCollisionException; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\ORMInvalidArgumentException; use Doctrine\ORM\PersistentCollection; @@ -20,7 +21,6 @@ use Doctrine\Tests\Models\CMS\CmsUser; use Doctrine\Tests\OrmFunctionalTestCase; use InvalidArgumentException; -use RuntimeException; use function get_class; @@ -1347,7 +1347,7 @@ public function testItThrowsWhenReferenceUsesIdAssignedByDatabase(): void // Now the database will assign an ID to the $user2 entity, but that place // in the identity map is already taken by user error. - $this->expectException(RuntimeException::class); + $this->expectException(EntityIdentityCollisionException::class); $this->expectExceptionMessageMatches('/another object .* was already present for the same ID/'); // depending on ID generation strategy, the ID may be asssigned already here diff --git a/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php b/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php index 31fa5ea8f64..0569bfd06dd 100644 --- a/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ORM/UnitOfWorkTest.php @@ -13,6 +13,7 @@ use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; use Doctrine\ORM\EntityNotFoundException; use Doctrine\ORM\Events; +use Doctrine\ORM\Exception\EntityIdentityCollisionException; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; @@ -41,7 +42,6 @@ use Doctrine\Tests\OrmTestCase; use Doctrine\Tests\PHPUnitCompatibility\MockBuilderCompatibilityTools; use PHPUnit\Framework\MockObject\MockObject; -use RuntimeException; use stdClass; use function assert; @@ -960,7 +960,7 @@ public function testItThrowsWhenApplicationProvidedIdsCollide(): void $phone2 = new CmsPhonenumber(); $phone2->phonenumber = '1234'; - $this->expectException(RuntimeException::class); + $this->expectException(EntityIdentityCollisionException::class); $this->expectExceptionMessageMatches('/another object .* was already present for the same ID/'); $this->_unitOfWork->persist($phone2);