An EntityManager is responsible for handling entities of all types and aggregates a single UnitOfWork member for its lifetime.
This means UnitOfWork itself must be able to handle entities of all types, which unfortunately it cannot. The reason is that out of its internal mapping structures, $identityMap uses normalized entity keys as array keys and therefore gets confused in the presence of entities of unrelated classes that have identical normalized primary keys -- for example, unrelated User and Group entities with the same single-column PK id, when the unit of work encounters a User and a Group that happen to also have the same value for id.
This PR fixes the issue by adding another level of mapping based on the entity class name, just like Doctrine's UnitOfWork implementation.
An
EntityManager
is responsible for handling entities of all types and aggregates a singleUnitOfWork
member for its lifetime.This means
UnitOfWork
itself must be able to handle entities of all types, which unfortunately it cannot. The reason is that out of its internal mapping structures,$identityMap
uses normalized entity keys as array keys and therefore gets confused in the presence of entities of unrelated classes that have identical normalized primary keys -- for example, unrelatedUser
andGroup
entities with the same single-column PKid
, when the unit of work encounters aUser
and aGroup
that happen to also have the same value forid
.This PR fixes the issue by adding another level of mapping based on the entity class name, just like Doctrine's
UnitOfWork
implementation.