2011-10-25 110 views
8

我正在努力與以下,在一個實體類中我有一個preUpdate lifeCycleCallback它必須堅持一個新的實體之前,它刷新auditTrail的變化。學說2.1堅持實體preUpdate lifeCycleCallback

在preRemove和prePersist中,它完美地工作,但在preUpdate中沒有任何事情發生。如果我自己調用flush,它會進入遞歸循環。

根據谷歌小組將其置於onFlush應該是一個選項,但在這種情況下,我不能訪問實體的舊值,以將這些舊值保存在審計跟蹤的新的其他實體中。

一些小例子,我嘗試到存檔:

<?php 
/** 
* @Entity 
* @HasLifeCycleCallbacks 
*/ 
class someEntity { 
    ... annotations ... 


    /** 
    * @PreUpdate 
    */ 
    public function addAuditTrail() { 
     $em = \Zend_Registry::get('doctrine')->getEntityManager(); 

     $entity = new AuditTrail(); 
     $entity->action = 'update'; 
     $entity->someField = $this->someField; 

     $em->persist($entity); //this just doesn't do anything :-(
    } 
} 
?> 

這不是真正的代碼,只是要說明你我想要什麼。我也嘗試過這樣的事情:

$em->getUnitOfWork()->computeChangeSet($em->getClassMetaData(get_class($entity)), $entity); 

這要根據這個主題的時候:http://groups.google.com/group/doctrine-user/browse_thread/thread/bd9195f04857dcd4

如果我再次調用flush但導致Apache因爲一些無限循環的崩潰。

任何人有我的想法?謝謝!

回答

6

你不應該在你的實體中使用entitymanager。如果你想補充審計跟蹤,你應該在「SomeEntity」實體映射到「審計跟蹤」實體和不喜歡

/** 
* @PreUpdate 
*/ 
public function addAuditTrail() { 
    $entity = new AuditTrail(); 
    $entity->action = 'update'; 
    $entity->someField = $this->someField; 

    $this->autitTrail->add($entity); 
} 

東西,如果你設置映射級聯選項,它會被堅持,當你堅持「SomeEntity」。

+0

爲什麼你不應該用我的實體內的實體管理器?如果將AuditEntity映射到SomeEntity,它將與數據庫關聯,這不是我想要複製我的實體並添加其他字段,如「action」= update等。此AuditEntity僅僅是一個示例,因爲對於我使用的審計:https://github.com/keesschepers/EntityAudit –

+0

我會使用eventmanager。想看看你的代碼,但沒有時間。 – tvlooy

+1

我終於(一年前!)使用事件管理器(EventSubscriber)在全球範圍內完成這些任務。我已經將它包含在我的框架中:https://github.com/php-pike/Pike(請看EntityAudit部分)謝謝! –

0

entitymanager-> persist()在preUpdate方法中不起作用。 取而代之,您可以將Audit Trail數據保存到會話中,並在沖刷「SomeEntity」之後,從會話中獲取數據並執行entitymanager-> persist(...)和entitymanager-> flush()

3

我在EventListener的preUpdate方法中遇到了同樣的問題。我通過將新實體存儲在屬性中並將新persist()和flush()調用移動到postUpdate方法來解決此問題。

class someEntity { 
... annotations ... 

protected $store; 

/** 
* @PreUpdate 
*/ 
public function addAuditTrail() { 
    //$em = \Zend_Registry::get('doctrine')->getEntityManager(); 

    $entity = new AuditTrail(); 
    $entity->action = 'update'; 
    $entity->someField = $this->someField; 

    // replaces $em->persist($entity); 
    $this->store = $entity; 
} 

/** 
* @PostUpdate 
*/ 
public function saveAuditTrail() { 
    $em = \Zend_Registry::get('doctrine')->getEntityManager(); 
    $em->persist($this->store); 
    $em->flush(); 
} 

}

+0

我知道它似乎有點'黑客'但我看不到這個用例的'官方'解決方案,我也使用了這種方法 –

+1

不幸的是,在生命週期回調中調用'flush()'並不被Doctrine支持,這似乎不適用於較新的Doctrine版本;我得到這個錯誤:http://www.doctrine-project.org/jira/browse/DDC-3218。 –

+0

請參閱此鏈接以瞭解如何正確執行此操作:http://stackoverflow.com/questions/16904462/adding-additional-persist-calls-to-preupdate-call-in-symfony-2-1。我希望有一種方法可以在實體類中實現,而不必創建一個單獨的全局類。 –