Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions lib/Doctrine/ORM/Exception/EntityIdentityCollisionException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Exception;

use function get_class;
use function sprintf;

final class EntityIdentityCollisionException extends ORMException
{
/**
* @param object $existingEntity
* @param object $newEntity
*/
public static function create($existingEntity, $newEntity, string $idHash): self
{
return new self(
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.

Otherwise, it might be an ORM-internal inconsistency, please report it.
EXCEPTION
,
get_class($newEntity),
$idHash,
get_class($existingEntity)
)
);
}
}
46 changes: 13 additions & 33 deletions lib/Doctrine/ORM/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreRemoveEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Exception\EntityIdentityCollisionException;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\ORM\Exception\UnexpectedAssociationValue;
use Doctrine\ORM\Id\AssignedGenerator;
Expand Down Expand Up @@ -1624,6 +1625,7 @@ public function isEntityScheduled($entity)
* the entity in question is already managed.
*
* @throws ORMInvalidArgumentException
* @throws EntityIdentityCollisionException
*
* @ignore
*/
Expand All @@ -1636,34 +1638,13 @@ public function addToIdentityMap($entity)
if (isset($this->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.
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,7 +21,6 @@
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\OrmFunctionalTestCase;
use InvalidArgumentException;
use RuntimeException;

use function get_class;

Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions tests/Doctrine/Tests/ORM/UnitOfWorkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down