Reza S Reza S - 4 months ago 24
PHP Question

Doctrine entitymanager clear doesn't fully clear

I have this piece of code:

$entityManager->clear('Reza\MyBundle\Entity\ListItem');

$identity = $entityManager->getUnitOfWork()->getIdentityMap();
foreach ($identity as $class => $objectlist) {
if ($class == 'Reza\MyBundle\Entity\ListItem') {
print "didn't fully clear, exiting..\n ";
exit;
}
}


You would think that after I pass in the classname to clear, you should not see those objects in the unit of work anymore, but by looking at the source I noticed that when you pass an argument to the
clear()
function it only detaches entities of that type. On the other hand, if I don't pass any arguments to
clear()
it detaches and does in fact clear, so the above code does not hit line 138, exit. So that means it not only detaches all entities, but also clears the unit of work.

Anyone has any thoughts on this? Should I file a bug with doctrine?

Answer

I would say that technically it is not a bug as clear() works as described in the documentation, see Doctrine2 API, documentation and source code (current version).

The clear() method is just a way to detach() all entities or entities of a specified type. It can be thought as a "Multi-Detach", it's purpose does not extend past detaching.

When detaching all entities using clear() Doctrine detaches the entities using the most efficient method possible. In the process the Identity Map Array is set to an empty array(). This will give the appears of what I believe you are referring to as cleared.

$entityManager->clear();
$identity = $entityManager->getUnitOfWork()->getIdentityMap(); 
//This will return a an empty array() to $identity
//therefore $identity['Reza\MyBundle\Entity\ListItem'] would be undefined

If we assume that data was retrieved for an entity of 'Reza\MyBundle\Entity\ListItem'. Then in the follow example we can see that the unit of work has at least 1 'Reza\MyBundle\Entity\ListItem' object.

$identity = $entityManager->getUnitOfWork()->getIdentityMap();
$count = count($identity['Reza\MyBundle\Entity\ListItem']);
//$count would be > 0;

However when you use clear($entityName) and clear by entity type, the cleared/detached entities are remove from the unit of work, it is only the array key [$entityName] that remains, not any of the objects.

$entityManager->clear('Reza\MyBundle\Entity\ListItem');
$identity = $entityManager->getUnitOfWork()->getIdentityMap(); 
$count = count($identity['Reza\MyBundle\Entity\ListItem']);
//$count would be == 0. All Objects cleared/detached.

This functionality is all that is specified by the documentation.

I do think the a feature request is in order, to make it work more consistently. When invoking clear($entityName) Doctrine should unset() the remaining key thereby making it undefined (cleared). This would allow us to more easily write code that would work whether we used clear() or clear($entityName).