Symfonyコンポーネント、イベントディスパッチャー(理論、パート1)

画像

こんにちは この翻訳は、 Event Dispatcherコンポーネントのドキュメントの最初の(2つあります)部分として考えられています。 このコンポーネントはSymfonyファミリーのコンポーネントの一部ですが、同時に独立しており、フレームワークを接続せずに使用できるため、さらに価値があります。 変換は、クラス間の相互作用を強化するために設計されたPHPのObserverパターンの軽量実装の概要として解釈できます。



コンポーネントファミリは現在PHP> = 5.3のバージョンとの互換性のために積極的に処理されており、 Symfony 2フレームワークの新しいバージョンで使用する予定です。 コンポーネントの新しいバージョンのコードはこちらにあります 新しいエディションのメソッドの名前と本質はほとんど変更されていないため、この資料はPHP 5.3でのコード学習コンポーネントに役立ちます。 それでは始めましょう。



イベントディスパッチャコンポーネント-それは何ですか?


Symfony Event Dispatcherは、オブザーバーデザインパターンの軽量実装であるPHPライブラリです。 これは、コードをより柔軟にする良い方法です。 また、コードをサードパーティ開発者による拡張(プラグイン開発)に適したものにする良い方法でもあります。 サードパーティのコードはコールバックを作成して特定のイベントをリッスンし、コードがこれらのイベントを通知するとディスパッチャーが呼び出しを行います。



とても速い


SymfonyのEvent Dispatcherの主な利点は、可能な限り高速であることです。 インターフェイスを宣言したり、複雑なクラスを拡張したりする必要はありません。イベントは単純な文字列であり、アラートコードは非常に軽量です。 追加の問題なしに、任意の数のハンドラーと呼び出しを追加します。



エントリー


オブジェクト指向のアプローチは、プロジェクトのコードを拡張可能にするための長い道のりを歩んできました。 機能が明確に定義されたクラスを作成することにより、コードの柔軟性が高まります。



ユーザーがクラスの動作を変更する場合、サブクラスを使用してクラスを拡張し、動作をオーバーライドできます。 しかし、ユーザーがサブクラスを作成して動作を変更した他のユーザーにこれらの変更を伝達したい場合、継承コードはあいまいになります。



人生の例として、クラスにプラグインシステムを提供したい場合があります。 プラグインは、他のプラグインと対話することなく、メソッドを追加したり、メソッドの前または最後に何かを実行できる必要があります。 この問題は、単一の継承では簡単に解決できず、複数の継承(PHPで可能だった場合)には欠点があります。



Symfony Event Dispatcherコンポーネントの主な目的は、オブジェクトが互いに知らなくても相互に通信できるようにすることです。 これは、中央オブジェクトであるディスパッチャによって可能になります。



オブジェクト(ハンドラー、リスナー)は、特定のイベントをリッスンするためにディスパッチャーと通信でき、他のいくつかはディスパッチャーにイベントを送信できます。 イベントがディスパッチされるとすぐに、ディスパッチャーは対応するハンドラーを開始します。



イベント


他の多くのObserver実装とは異なり、クラスを作成して新しいイベントを作成しないでください。 もちろん、すべてのイベントはオブジェクトのままですが、すべてのイベントはsfEvent組み込みクラスのインスタンスです。



注:もちろん、イベントをさらに拡張するためにsfEventクラスを拡張するか、いくつかの制限を含めることができますが、ほとんどの場合、これにより新しい不当なレベルの複雑さが追加されます。



イベントは文字列によって一意に識別されます。 慣例により、イベント名には小文字、数字、アンダースコア(_)を使用するのが最善です。 また、イベントを整理しやすくするために、イベント名の前に名前空間の前にピリオド(。)を付けるのが良い規則です。



よく知られたイベントの例を次に示します。

change_culture

response.filter_content




お気づきかもしれませんが、イベント名には、イベントが発生したときに何が起こるかを示す単語が含まれています。



ディスパッチャー


ディスパッチャーは、ハンドラーの登録を制御し、イベントの1つが発生したときにそれらを呼び出すオブジェクトです。

デフォルトでは、ディスパッチャークラスはsfEventDispatcherです:

$dispatcher = new sfEventDispatcher();





イベントオブジェクト


sfEventクラスのイベントオブジェクトは、宣言されているイベントに関する情報を保存します。 そのコンストラクタは3つの引数を取ります。 ほとんどの場合、イベントはオブジェクトのコンテキストで発生し、最初の引数はほとんど常に$ thisです。

$ event = new sfEvent($ this , 'user.change_culture' , array( 'culture' => $culture));



イベントオブジェクトには、イベント情報を取得するためのいくつかのメソッドがあります。

イベントオブジェクトは、パラメーターを取得するための配列としても使用できます。

echo $ event [ 'culture' ];





ハンドラーを追加する


明らかに、便利になる前に、いくつかのハンドラをディスパッチャにアタッチする必要があります。 ディスパッチャメソッドconnect()を呼び出すとPHP callableがイベントに関連付けられます



connect()メソッドは2つの引数を取ります。

注: PHP callableは、call_user_func()関数で使用できるPHP変数であり、is_callable()関数に渡されるとtrueを返します。 文字列は関数を表し、配列はオブジェクトメソッドまたはクラスメソッドを表すことができます。

$dispatcher->connect( 'user.change_culture' , $callable);



ハンドラーは、イベントマネージャーを使用して登録されるとすぐに、対応するイベントが呼び出されるのを待ちます。 イベントマネージャーは、すべてのイベントハンドラーの記録を保持し、イベントが発生したときにトリガーするイベントハンドラーを把握しています。



注:ハンドラーは、イベントマネージャーによって、アタッチした順に呼び出されます。



前の例では、user.change_cultureイベントがオブジェクトによって宣言されると、ディスパッチャによって$ callableが呼び出されます。

ハンドラーが呼び出されると、ディスパッチャーはsfEventオブジェクトをパラメーターとして渡します。 つまり、ハンドラーは最初の引数としてイベントオブジェクトを受け取ります。



イベントのお知らせ


イベントは、次の3つの方法のいずれかで宣言できます。

通知()


notify()メソッドは、すべてのハンドラーを起動します。

$dispatcher->notify($ event );





notify()メソッドを使用すると、宣言されたイベントの登録済みハンドラーがすべて実行されたことを確認できますが、サブジェクトに値を返すことはできません。



notifyUntil()


場合によっては、ハンドラーがイベントを停止できるようにして、他のハンドラーがイベントについて学習しないようにする必要があります。 この場合、notify()の代わりにnotifyUntil()を使用する必要があります。 次に、ディスパッチャーは、いずれかのハンドラーがtrueを返すまですべてのハンドラーを呼び出し、その後、イベントに対する反応を停止します。

$dispatcher->notifyUntil($ event );



チェーンを停止するハンドラーは、setReturnValue()メソッドを呼び出してサブジェクトに値を返すこともできます。



イベントを発生させた人は誰でもisProcessed()メソッドを呼び出すことにより、ハンドラーがイベントを処理したことを確認できます。

if ($ event ->isProcessed())

{

$ret = $ event ->getReturnValue();



// ...

}








フィルター()


filter()メソッドでは、すべてのハンドラーが、イベント作成者から2番目の引数で渡され、ハンドラーによって2番目の引数として受信された特定の値をフィルタリングする必要があります。

$dispatcher->filter($ event , $response->getContent());





すべてのハンドラーは値を取得し、変更されたかどうかに応じてフィルター処理された値を返す必要があります。 すべてのハンドラーが呼び出されることが保証されています。



イベントを宣言した人は、getReturnValue()メソッドを呼び出すことにより、フィルタリングされた値を取得できます。

$ret = $ event ->getReturnValue();



第2部では、Event Dispatcherを使用した実用的な例を翻訳する予定です。 そして、おそらく、実際のプロジェクトでコンポーネントを使用することに関する別のトピックがあるでしょう。



All Articles