2013-02-14 66 views
1

我試圖弄清楚如何在preUpdate方法中回滾已更改實體的狀態(如果這有所幫助,我使用註釋方法)。如何重置我的preUpdate方法中的學說實體?

我試過使用EntityManager::refresh($entity),雖然它似乎恢復實體,它仍然繼續並將更改保存到數據庫。

我讀過我需要通過調用$em->getUnitOfWork()->computeChangeSet($em->getClassMetaData(get_class($this)), $this);來重新計算更改集,但這並不能解決問題。

反正有沒有辦法讓UnitOfWork忽略更改/重新正確計算?

<?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"); 

輸出:

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 

一切看起來不錯,但是當我看到我的數據庫日誌我看到:

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

回答

2

這已經由ORM本身處理(見https://github.com/doctrine/doctrine2/blob/2.3.2/lib/Doctrine/ORM/UnitOfWork.php#L970-L974

這裏的問題我s DateTime實例分配給date_last_seen(或更好地映射到它的字段)具有不同的對象散列(與spl_object_hash()一起檢查它)。

對於ORM,這是一個變更集。要有效重置您的實例,您需要手動撥打Doctrine\ORM\UnitOfWork#clearEntityChangeSet(spl_object_hash($this))

,考慮到這碼出實體移動到一個專門的事件監聽器:你的實體不應該知道的EntityManager或約以任何方式持久層。

+0

我追溯了'recomputeSingleEntityChangeSet',但我認爲問題是['$ orgValue!== $ actualValue'](https://github.com/doctrine/doctrine2/blob/2.3.2/lib/ Doctrine/ORM/UnitOfWork.php#L876-880)是錯誤的,所以變更集不會被填充,['array_merge'](https://github.com/doctrine/doctrine2/blob/2.3.2/lib/Doctrine/ ORM/UnitOfWork.php#L883-889)永遠不會被調用來重置值。 – hafichuk 2013-02-15 15:43:47

+0

嗯......你說得對。無論如何,您需要手動清除變更集。 – Ocramius 2013-02-15 16:30:41

+1

感謝您的驗證。我還發現I *應該使用'preFlush' *,它在計算變更集之前被調用。更有效率並繞過問題afaik。 – hafichuk 2013-02-15 16:40:37