1
0
mirror of synced 2025-02-09 00:39:25 +03:00

Avoid conflicts due to spl_object_hash().

When merging an entity with a to-many association, it will store the
original entity data using the object hash of the to-be-merged entity
instead of the managed entity. Since this to-be-merged entity is not
managed by Doctrine, it can disappear from the memory. A new object
can reuse the same memory location and thus have the same object hash.
When one tries to persist this object as new, Doctrine will refuse it
because it thinks that the entity is managed+dirty.

This patch is a very naive fix: it just disables storing the original
entity data in case of to-many associations. It may not be the ideal
or even a good solution at all, but it solves the problem of object
hash reuse.

The test case relies on the immediate reusing of memory locations by
PHP. The variable $user has twice the same object hash, though referring
a different object. Tested on PHP 5.6.17

Without the fix, the test fails on the last line with:
A managed+dirty entity Doctrine\Tests\Models\CMS\CmsUser@[...] can not
be scheduled for insertion.
This commit is contained in:
Mathieu De Zutter 2016-03-01 10:58:37 +01:00 committed by Marco Pivetta
parent 5365a418e9
commit 95dcf51ad5
2 changed files with 35 additions and 1 deletions

View File

@ -3423,7 +3423,7 @@ class UnitOfWork implements PropertyChangedListener
$managedCol->setOwner($managedCopy, $assoc2);
$prop->setValue($managedCopy, $managedCol);
$this->originalEntityData[spl_object_hash($entity)][$name] = $managedCol;
// $this->originalEntityData[spl_object_hash($entity)][$name] = $managedCol;
}
if ($assoc2['isCascadeMerge']) {

View File

@ -0,0 +1,34 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\OrmFunctionalTestCase;
class OidReuseTest extends OrmFunctionalTestCase
{
private $userId;
/**
* {@inheritDoc}
*/
protected function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testOidReuse()
{
$user = new CmsUser();
$this->_em->merge($user);
$user = null;
$user = new CmsUser();
$this->_em->persist($user);
}
}