私はSymfony2フレームワークで作業していて、Doctrineサブスクライバーとリスナーのどちらを使用するのか疑問に思っています。リスナー向けのDoctrineのドキュメントは非常に明確ですが、サブスクライバーはかなり見過ごされています。Symfonyのクックブックエントリも同様です。
7 に答える
私の見解では、大きな違いは 1 つだけです。
- Listener は、リッスンするイベントを指定してサインアップします。
- サブスクライバーには、リッスンしているイベントをディスパッチャーに伝えるメソッドがあります
これは大きな違いのようには思えないかもしれませんが、考えてみると、どちらか一方を使いたい場合がいくつかあります。
- ディスパッチャーは登録時に設定されるため、さまざまなイベントを持つ多くのディスパッチャーに 1 つのリスナーを割り当てることができます。すべてのメソッドがリスナーに配置されていることを確認するだけで済みます
- サブスクライバーが登録されているイベントは、実行時およびサブスクライバーの登録後でも、戻り値を変更することで変更できます
getSubscribedEvents
(非常にノイズの多いイベントをリッスンしていて、何かを 1 回だけ実行したい場合を考えてみてください)。
私が気付いていない他の違いがあるかもしれません!
それが偶然なのか意図的なものなのかはわかりません..しかし、サブスクライバーはリスナーよりも優先されます - https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass .php#L73-L98
教義側からは、それが何であるか (リスナーまたはサブスクライバー) は気にせず、最終的に両方がリスナーとして登録されます - https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/EventManager.php #L137-L140
これは私が見つけたものです。
もう 1 つの重要な点: Doctrine EventSubscribers では優先度を設定できません。
この問題の詳細については、こちらをご覧ください
このsymfony2 doc ページの記事のように、1 つのクラスで複数のイベントを処理する場合は、イベント サブスクライバーを使用する必要があります。、イベント リスナーは 1 つのイベントしか管理できないことに気付くかもしれませんが、1 つのエンティティに対して複数のイベント、prePersist、preUpdate、postPersist などを処理したいとします。イベント リスナーを使用する場合、複数のイベント リスナーをコーディングする必要があります。イベントごとに1つですが、イベントサブスクライバーを使用する場合は、イベントサブスクライバーを1つのクラスにコーディングするだけで済みます。イベントサブスクライバーを使用すると、1つのクラスで複数のイベントを管理できることがわかります。モデルのビジネス ニーズに焦点を当てたコードを作成するには、たとえば、エンティティのグループに対してのみ複数のライフサイクル イベントをグローバルに処理したい場合があります。これを行うには、親クラスをコーディングし、その中でそれらのグローバル メソッドを定義します。次に、エンティティにそのクラスを継承させ、後でイベント サブスクライバーで、必要なすべてのイベントをサブスクライブします。preUpdate、postPersist など...そしてその親クラスを要求し、それらのグローバル メソッドを実行します。
どちらも、特定のイベントの前後に永続化などで何かを実行できます。
ただし、リスナーでは、エンティティ内にカプセル化された動作のみを実行できます。たとえば、"date_edited" タイムスタンプを更新することが考えられます。
エンティティのコンテキストの外に移動する必要がある場合は、サブスクライバーが必要になります。良い例は、外部 API を呼び出す場合、またはエンティティに直接関連しないデータを使用または検査する必要がある場合です。