2011-10-11 35 views
6

我使用的是Doctrine 2实体。我们有一些实体在将其保存到数据库时必须更新相关项目。例如,当用户记录被修改时,我们将其保存为新记录,并将“非活动”字段设置为“假”。但是,我们必须将该用户的所有先前记录的“非活动”字段设置为“真”。这样做是为了保留审计历史。这是一个传统数据库,所以更改结构不是一个选项。由于Doctrine通过将对象传递给persist对象(persist ::($ thisObj))来保存对象,而不是具有保存方法的对象($thisObj->save()),所以我们不能只从一个保存方法父对象。我在这里看到的唯一选择是试图扩展'坚持'的对象,但这听起来像一只鹅群,只是等待发生。学说2,需要执行代码前持久性/后持久性

我发现了一些有关事件的信息,但没有看到如何添加它们以使事件在特定实体持续存在时触发特定函数。

如何向我的某些实体添加预保存/保存后功能?

回答

12

那么,你可能已经知道http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html对不对?

您添加的实体包含回调的注解,然后创建该实体特定功能(这需要公开),并与@PrePersist或@PostPersist或任何注释它们。所谓prePersist,postPersist等

另一种方法是创建一个事件订阅,注册一个与教义事件管理和实施方法,他们获得通过的EventArguments对象包含了有关所发生的事件的实体。

我知道这是对您的问题的一个非常普遍的答案,但您需要针对问题所在的位置进行更具体的解答。

请不要发放实体管理器并覆盖坚持的方法,有很多方法可以做到你所需要的更清晰的方法,据我所知。

7

这实际上很简单,做你想做的事情。它不需要与活动经理或任何类似的复杂活动。你使用了一种叫做“生命周期回调”的东西。这些函数主义的实体的“生命周期”过程中自动运行,即:prePersist,postPersist,更新前,postUpdate等,您可以在这里找到完整的列表:http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html

添加此功能,您的实体的过程非常简单。

  1. 在你的实体的注释部分,包括以下标签:“@HasLifecycleCallbacks”。这告诉Doctrine它应该搜索实体以便在各种事件中运行功能
  2. 在您的实体中编写一个公用函数,您想在特定事件上触发该函数。
  3. 将一个注释放在函数的上方,指出应该使用哪个事件来处理。

例如,看一下下面的代码:

/** @PostPersist */ 
public function doSPostPersist() { 
    $this->tester = 'Value changed by post-persist'; 
} 

我发现,有时候事件索性不火了,我还不知道是什么原因。但是当他们开火时,他们会可靠地射击。

+2

OK,想通了,为什么事件有时“干脆拒绝解雇”。 prePersist/posPersist事件仅在保存新记录时才会发生。如果您正在更新现有记录,则preUPdate/postUpdate会消失。因此,即使调用持久化方法,如果要保存现有对象,也应用preUpdate/postUpdate生命周期事件。 –

+0

感谢您带领我走向正确的方向。一个后续行动:我从基础类中获取所有实体,以提供一些常规功能。我讨厌必须在每个实体中放置一个事件,因为在我的情况下,我真的只是使用postLoad来激发构造函数,并且我希望在所有实体中都这样做。有什么办法可以将它移到基类中,而无需在entitiy中进行额外的复制和粘贴? – redreinard

+0

第二点对我来说非常有用!非常感谢你! –

2

不要忘记启用生命周期回调在你的类注释:

/** 
* Report\MainBundle\Entity\Serveur 
* @ORM\HasLifecycleCallbacks 
*/ 
class Serveur { 
+0

是否需要“ORM \”部分?没有它,它似乎可以很好地工作,但我想用最好的做法。 – redreinard

+0

这不是最佳实践,只是映射管理器的别名,使用Doctrine \ ORM \ Mapping作为ORM; ... /** * @ORM \ HasLifecycleCallbacks * / – ROLO