hafichuk
hafichuk

Reputation: 10781

How do I reset a doctrine entity in my preUpdate method?

I'm trying to figure out how to rollback the state of a changed entity while in the preUpdate method (I'm using the annotation method if that makes a difference).

I've tried using the EntityManager::refresh($entity) and while it does seem to revert the entity, it still goes ahead and saves the changes to the database.

I've read that I need to recalculate the change set by calling $em->getUnitOfWork()->computeChangeSet($em->getClassMetaData(get_class($this)), $this); however this doesn't do the trick.

Is there anyway to get the UnitOfWork to ignore the changes/re-calculate properly?

<?php 
class Status extends Entity {

    /**
     * @PreUpdate
     */
    public function preUpdate() {
        if (!$this->canSave()) {
            $this->reset();
        }
    }

    public function reset() {
        $em = self::getEntityManager();
        $em->refresh($this);
        $em->getUnitOfWork()
           ->computeChangeSet($em->getClassMetaData(get_class($this)), $this);
    }

    public function canSave() { return false; }
?>

<?php
// Bootstrap for testing/debugging
include 'common.php';

$log = \Zend_Registry::get('log');

$x = Status::find(31); // Retrieve entity from DB
$log->debug("Original: " . $x->getDateLastSeen() . "\n");

$x->setDateLastSeen(new \DateTime());
$log->debug("Set to: " . $x->getDateLastSeen() . "\n");

$x->save();
$log->debug("Saved to: " . $x->getDateLastSeen() . "\n");

Outputs:

2013-02-14T23:13:22+00:00 DEBUG (7): Original: 2013-02-14 23:08:22
2013-02-14T23:13:22+00:00 DEBUG (7): Set to: 2013-02-14 23:13:22
2013-02-14T23:13:22+00:00 DEBUG (7): Saved to: 2013-02-14 23:08:22

Everything looks okay, however when I look at my database log I see:

409705 Query    UPDATE devices_statuses SET date_last_seen = '2013-02-14 23:13:22' WHERE id = 31
409705 Query    commit

Upvotes: 1

Views: 2971

Answers (1)

Ocramius
Ocramius

Reputation: 25440

This is already handled by the ORM itself (see https://github.com/doctrine/doctrine2/blob/2.3.2/lib/Doctrine/ORM/UnitOfWork.php#L970-L974 )

The problem here is that the DateTime instance assigned to date_last_seen (or better the field mapped to it) has a different object hash (check it with spl_object_hash()).

For the ORM, this is a changeset. To effectively reset your instance, you will need to manually call Doctrine\ORM\UnitOfWork#clearEntityChangeSet(spl_object_hash($this)).

Also, consider moving this code out of the entity into a dedicated event listener: your entity should not be aware of the EntityManager or about the persistence layer in any way.

Upvotes: 2

Related Questions