Skip to content


DDC-74: Updates get lost when Lifecycle Events (@PreUpdate) are invoked #5252

doctrinebot opened this Issue · 5 comments

1 participant


Jira issue originally created by user nicokaiser:

When Lifecycle Events are invoked on entity update (@PreUpdate), the entity is not updated properly in the database.

This code creates a User* object, sets its name to "Bob" and its value to empty, then updates the object and updates the *name to "Alice".

$user = new User;

However, when the User class has a @PreUpdate event that e.g. sets the value* to "Hello World", the name change gets lost and only the *value is updated by the second flush() call.

This is a critical bug which prevents creation of entities that simulate the "Timestampable" behaviour of Doctrine 1.x...


Comment created by @beberlei:

I think this might be a hen-egg problem.

@PreUpdate is only invoked after it is calculated that a change occured on all those entities that have updates. After a change in @PreUpdate events there would have to be another calculation of changes on all those entities, which would probably mean a significant performance hit.


Comment created by rickdt:

I may not know all the consequences of this, but I think I have a fix for this bug.

In the class ORM\UnitOfWork

As I understand it, computeSingleEntityChangeSet() is called to update the changeset and _originalEntityData is set to the current values.

But, I see that the old changes are lost.

If i modify the function computeSingleEntityChangeSet to merge the changeset, it works.

At line 656 replace

$this->_entityChangeSets[$oid] = $changeSet;

By :

    $this->_entityChangeSets[$oid] += $changeSet;
else {
    $this->_entityChangeSets[$oid] = $changeSet;

Here is my test case :

$qb = new \Doctrine\ORM\QueryBuilder($em);
            ->from('Entity\FNA', 'fna')
            ->andwhere($qb->expr()->eq('', ':fna_id'));
$qb->setParameter('fna_id', 1);
$query = $qb->getQuery();

$fna = $query->getSingleResult();


AND The preUdate :

 * @PreUpdate
public function onPreUpdate($args=false)
        $this->modified_at = new \DateTime();

Comment created by romanb:

Indeed this looks like a good fix except that the addition has to be the other way around so that when the same field is changed twice, first before the flush and then in a lifecycle callback/event the change from the callback prevails.

I will work on this and write a test for it.

Thanks Eric.


Comment created by romanb:

Fixed now.

Thanks Nico for reporting and thanks Eric for the suggestion!


Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.0-ALPHA4 milestone
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.