2011-10-11 5 views
6

私はDoctrine 2エンティティを使用しています。データベースに保存するときに関連項目を更新する必要があるエンティティがいくつかあります。たとえば、ユーザーレコードが変更された場合、「無効」フィールドが「偽」に設定された新しいレコードとして保存されます。しかし、そのユーザーの以前のすべてのレコードの '非アクティブ'フィールドを 'true'に設定する必要があります。これは、監査履歴を保持するために行われます。これはレガシーデータベースなので、構造を変更することはオプションではありません。Doctrine 2、コードを実行する必要がありますpre-persist/post-persist

Doctrineは保存メソッド($thisObj->save())を持つオブジェクトではなく、persisterオブジェクト(persist :: $ thisObj)にオブジェクトを渡すことでオブジェクトを保存するので、 'save'メソッドを親オブジェクト。私がここに見る唯一のオプションは '永続的な'オブジェクトを拡張しようとすることですが、それは起こるのを待っているガチョウのように聞こえます。

イベントに関する情報はいくつか見つかりましたが、特定のエンティティが永続化されたときにイベントを発生させるためのイベントの追加方法はわかりません。

一部のエンティティに保存前/保存後の機能を追加するにはどうすればよいですか。

答えて

12

だからおそらくすでにhttp://www.doctrine-project.org/docs/orm/2.1/en/reference/events.htmlを知っているでしょうか?

エンティティにコールバックが含まれている注釈を追加し、そのエンティティで特定の関数(パブリックにする必要がある)を作成し、@PrePersistまたは@PostPersistなどで注釈を付けます。

他の方法は、イベント加入者を作成し、それをdoctrineイベントマネージャに登録し、prePersist、postPersistなどのメソッドを実装することです。発生したイベントに関連するエンティティを含むEventArgumentsオブジェクトが渡されます。

私はこれがあなたの質問に対する非常に一般的な答えであることを知っていますが、あなたの問題がどこにあるのかを少し具体的にする必要があります。

エンティティマネージャを使い果たして永続メソッドを上書きしないでください。必要なことを実行するための方法があります。

7

あなたがしたいことは、実際にはとても簡単です。イベントマネージャーやそのような複雑なものでは、ドークを必要としません。 「ライフサイクルコールバック」と呼ばれるものを使用します。これらは、エンティティのライフサイクル中にDoctrineが自動的に実行する関数です。つまり、prePersist、postPersist、preUpdate、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が火を放ちます。したがって、既存のオブジェクトを保存する場合は、persistメソッドを呼び出しても、preUpdate/postUpdateライフサイクルイベントが適用されます。 –

+0

私を正しい方向に導いてくれてありがとう。 1つのフォローアップ:基本クラスからすべてのエンティティを継承して、いくつかの一般的な機能を提供します。私はすべてのエンティティにイベントを配置する必要はありません。なぜなら、私の場合、私は実際にpostLoadを使用してコンストラクタを起動しています。これを基本クラスに移動するには、余分なコピー&ペーストをentitiyする必要はありませんか? – redreinard

+0

2番目のポイントは私にとって非常に便利でした!どうもありがとうございました! –

2

は、あなたのクラスのアノテーションでライフサイクルコールバックを有効にすることを忘れないでください:

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

「ORM」の部分は必要ですか?それがなければ私にとってはうまくいくようですが、私はベストプラクティスに行きたいです。 – redreinard

+0

これはベストプラクティスではなく、マッピングマネージャのエイリアスです。 ORMとしてDoctrine \ ORM \ Mappingを使用します。 ... /** * @ORM \ HasLifecycleCallbacks * / – ROLO

関連する問題