我正在努力解决以下问题,在实体类中我有一个preUpdate lifeCycleCallback,它必须在刷新auditTrail的更改之前保留一个新实体。
在preRemove和prePersist中,这可以很好地工作,但在preUpdate中没有任何事情发生。如果我自己调用flush,它会进入递归循环。
根据教学用户的Google群组,将其放入onFlush应该是一个选项,但在这种情况下,我无法访问实体的旧值,以将此旧值保存在audittrail的新其他实体中。 / p>
我想要存档的一些小例子:
<?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崩溃。
任何有想法的人?谢谢!
答案 0 :(得分:6)
您绝不应在实体内使用entitymanager。如果您想添加审计跟踪,您应该将“SomeEntity”实体映射到“AuditTrail”实体并执行类似
的操作/**
* @PreUpdate
*/
public function addAuditTrail() {
$entity = new AuditTrail();
$entity->action = 'update';
$entity->someField = $this->someField;
$this->autitTrail->add($entity);
}
如果在映射上设置了级联选项,则在持久保存“SomeEntity”时它将保持不变。
答案 1 :(得分: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();
}
}
答案 2 :(得分:0)
entitymanager-&gt; persist()在preUpdate方法中不起作用。 除此之外,您可以将AuditTrail数据保存到会话中,并在刷新“SomeEntity”之后,从会话中获取数据并执行entitymanager-&gt; persist(...)和entitymanager-&gt; flush()