ホームページ > php教程 > php手册 > zendframework イベント管理 (2)

zendframework イベント管理 (2)

WBOY
リリース: 2016-08-04 08:53:14
オリジナル
851 人が閲覧しました

最初に明確にする必要があるいくつかの質問:

Q1. イベントとは何ですか?

A: イベントとは名前付きの動作です。この動作が発生すると、イベントがトリガーされたと言われます。

Q2.モニターとは何ですか?

A: リスナーはイベントの論理式を決定し、イベントによってトリガーされます。リスナーとイベントは多くの場合ペアになります。もちろん、1 つのイベントが複数のリスナーに対応することもあります。リスナーはイベントに反応します。イベントがトリガーされたとき、どのように反応するかはリスナー次第です。このようにして、複数のイベントが発生すると、単一のリスナーが反応する可能性があります。イベントには複数のリスナーが反応することもあります。 (一言で言えば、リスナーとイベントの関係は 1 対多または多対 1 のいずれかになります)

Q3. イベントマネージャーは何に使用されますか?

A: イベント マネージャー (EventManager) は、名前からわかるように、イベントを管理するために使用されます。しかし、彼はどうやってそれを管理しているのでしょうか?イベント マネージャーは、多くの場合、複数のイベントに対して複数のリスナーを集約します (ここでのイベントとリスナーは両方とも不定です (つまり、1 つまたは複数になる可能性があります))。イベント マネージャーは、イベントのトリガーも担当します。

一般的に、私たちは出来事を表すためにオブジェクトを使います。イベント オブジェクトは、イベントがいつどのようにトリガーされるかなど、イベントの基本要素を記述します。

イベントの基本要素について: イベント名、ターゲット (イベントをトリガーするオブジェクト、通常はイベント オブジェクト自体)、およびイベント パラメーター。イベントは動作に相当すると前に述べました。プログラムでは、動作を表現するためにメソッドや関数を使用することがよくあります。したがって、イベント パラメーターは関数パラメーターでもあることがよくあります。

共有マネージャーについても: 前述したように、1 つのイベントは複数のリスナーをターゲットにすることができます。これは、共有マネージャーによって実現されます。 EventManager の実装には、SharedEventManagerInterface (コンストラクターまたは setSharedManager でのコード インジェクションを使用します。詳細についてはソース コードを参照してください)) が含まれ (結合)、SharedEventManagerInterface は、リスナーを集約するオブジェクトを記述します。これらのリスナーは、指定された ID を持つオブジェクトにのみ接続されます。イベント。 SharedEventManager はイベントをトリガーせず、リスナーを提供してイベントに接続するだけです。 EventManger は、SharedEventmangaer にクエリを実行することで、特定の識別子を持つリスナーを取得します。

EventManager のいくつかの重要な動作:

1. イベントを作成します: イベントの作成は、実際には EventManagerInterface のインスタンスを作成するだけです

2. イベントのトリガー: 通常、トリガーはイベントの動作で使用され、動作の実行時にイベントを直接トリガーできます。関数プロトタイプ:trigger($eventName,$target=null,$argv=[]); $eventName は通常、時間アクション名 (通常は __FUNCTION__ で置き換えられます)、$target はイベント オブジェクト自体であり、$this で置き換えることができます。 $argv は受信イベントのパラメータ (通常はイベント動作のパラメータ) です。

もちろん、イベントをトリガーする方法は 1 つだけではなく、triggerUntil、triggerEvent、triggerEventUntil もあります。名前から、トリガー クラスは単にイベントをトリガーするだけであり、イベント インスタンスを作成するために実装する必要はありません。トリガーはイベント名のみで必要です。イベントをトリガーするだけでなく、リスナーもトリガーします。イベント インスタンスが必要です。 until サフィックスが付いているメソッドにはコールバック関数が必要で、各リスナーの結果はコールバック関数に渡されます。コールバック関数が true bool 値を返す場合、EventManager はリスナーをショートする必要があります。 (短絡については、以下の短絡を参照してください)

詳細については、公式 API または EventMangerInterface の特定のコメントを確認してください。

3. リスナーを作成してイベントに接続します :

リスナーはEventManagerまたはSharedEventManagerを通じて作成できます。どちらも Attach メソッドを使用しますが、パラメータが若干異なります。

まず EventManager メソッドを見てみましょう:

メソッドのプロトタイプ:attach($eventName, callable $listener, $priority = 1)

非常にシンプルで、必要なのはイベント名と呼び出し可能な関数だけで、最後にデフォルトの優先度は 1 です(zend の組み込みイベントの優先度はほとんどが負の数値なので、イベントの優先度をカスタマイズしたい場合は、リスナー 比較的高い場合は、正の数値を直接割り当ててください)

呼び出し可能な関数はリスナーです。イベント名には特殊なケース「*」があります。これは通常のマッチングに似ており、すべてのイベントをこのリスナーに接続します。

次に SharedEventManager メソッドを見てみましょう:

メソッドのプロトタイプ:attach($identifier, $eventName, callable $listener, $priority = 1);

以前との唯一の違いは、追加の識別子パラメータがあることです。識別子に関するソースコードのコメントは次のとおりです:

SharedEventManagerInterface インスタンスから共有シグナルをプルするために使用されます;

SharedEventmanager インスタンスから共有シグナルをプルするために使用されます。私の理解によれば、識別子は配列です: イベント (SharedEventmanager はイベントを作成できないことに注意してください) が識別子を定義している場合、それはイベントが共有可能であることを意味します。アタッチを使用してリスナーを作成するときに、SharedEventManger インスタンスに識別子パラメーターを渡します。 EventManager は、識別子パラメーターを使用してすべてのリスナーをクエリできます。

混乱を招くのは、イベント名があるため、イベント名を通じて関連するリスナーをクエリできるのに、なぜわざわざ identifier 属性を追加する必要があるのか​​ということです。私が検討しているのは、イベントの継承の問題です。イベント動作アクトを含むイベント クラス Foo があり、SubFoo が Foo クラスを継承し、内部のイベント動作アクトをオーバーライドするとします。両方のクラスのイベント アクションは、同じイベント名 act を持ちます。このとき、イベント名でリスナーにクエリを実行すると、明らかに競合が発生します。このとき、識別子[__CLASS__, get_class($this)]を定義し、リスナーに識別子をSubFooとして指定すると、明らかにSubFooクラスのイベント動作と一致します。

上記では、SharedEventManager を通じて複数のイベントをリッスンでき、リスナー集約を通じて実装することもできます。 ZendEventManagerListenerAggregateInterface を通じて、クラスが複数のイベントをリッスンし、1 つ以上のインスタンス メソッドをリスナーとして接続できるようにします。同じインターフェイスでは、attach(EventManagerInterface $events) と detach(EventManagerInterface $events) も定義されます。 Attach の特定の実装では、EventManager インスタンスの Attach メソッドを使用して複数のイベントをリッスンします。

リーリー

Aggregateを使用する利点:

1. ステートフル リスナーの使用を許可します

2. 複数の同様のリスナーを 1 つのクラスに結合し、すべてを一度に接続します

イントロスペクション リスナーによって返された結果

リスナーはありますが、リスナーが返す結果をどのように受け取るのでしょうか? EventManager のデフォルト実装は、ResponseCollection のインスタンスを返します。このクラスは、PHP の SplStack から継承します。基本的な構造はスタックであるため、応答を逆の順序で走査することができます。

ResponseCollection にはいくつかの便利なメソッドが用意されています:

first(): 最初の結果を取得します

last(): 最後の結果を取得します

contains($value): スタックに特定の値が含まれているかどうかを確認し、含まれている場合は true を返し、そうでない場合は false を返します。

短いループリスナーの実行:

ショートとは何ですか?結果が得られるまで何かを実行するとします。これがループです。この処理の結果が事前にわかっている場合 (たとえば、以前にこの処理を実行したことがある場合)、現時点では短いループを実行するだけで済みます。

EventManagerを追加する際にキャッシュの仕組みを用意しています。メソッド内でイベントをトリガーし、キャッシュされた結果が見つかった場合は直接返します。キャッシュされた結果が見つからない場合は、後で使用できるようにトリガーされたイベントをキャッシュします。実際、これはコンピュータ ハードウェアのキャッシュと同じです。

EventManager コンポーネントは、1.triggerUntil(); 2.triggerEventUntil の 2 つの処理メソッドを提供します。どちらのメソッドも最初のパラメータとしてコールバック関数を受け入れます。コールバック関数が true を返した場合、実行は停止します。

リーリー

上記の例から、実行が停止する場合は、スタック内の最後の結果が要件を満たしていることが原因である可能性が高いことがわかります。このように、結果を返すだけで済みますが、なぜ追加の計算を実行する必要があるのでしょうか?

処理はイベントで実行を停止しますが、リスナーで実行を停止することもできます。なぜかというと、以前にもあるイベントを受け取っていて、今度は同じイベントを受け取ったので、当然前回の結果が使えるからです。この場合、リスナーは stopPropagation(true) を呼び出し、EventManager は追加のリスナーに通知せずに直接戻ります。

リーリー

当然,使用触发器范例可能会导致歧义,毕竟你并不知道最终的结果是否满足要求。

  Keeping it in order.

  偶尔你会关心监听器的执行顺序。我们通过监听器的优先级来控制执行顺序(上面说讲的短回路也会影响执行顺序)。每一个EventManager::attach()和SharedEventManager::attach()都会接受一个而外的参数:priority。默认情况下为1,我们可以省略该参数。如果你提供了该参数:高优先级执行的早,低优先级的可能会推迟执行。

  自定义事件对象:

  我们之前使用trigger()触发事件,在这同时我们也创建了事件。但trigger()的参数有限,我们只能指定事件的对象,参数,名称。实际上我们可以创建一个自定义事件,在Zendframework里面有个很重要的事件:MvcEvent。很显然MvcEvent便是一个自定义事件,该事件组合了application实例,路由器,路由匹配对象,请求和应答对象,视图模型还有结果。我们查看MvcEvent的源码会发现MvcEvent类实际上继承了Event类。同理我们的自定义事件对象也可以继承Event类或者继承MvcEvent。

<span style="color: #800080;">$event</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> CustomEvent();
</span><span style="color: #800080;">$event</span>->setName('foo'<span style="color: #000000;">);
</span><span style="color: #800080;">$event</span>->setTarget(<span style="color: #800080;">$this</span><span style="color: #000000;">);
</span><span style="color: #800080;">$event</span>->setSomeKey(<span style="color: #800080;">$value</span><span style="color: #000000;">);

</span><span style="color: #008000;">//</span><span style="color: #008000;">injected with event name and target:</span>
<span style="color: #800080;">$events</span>->triggerEvent(<span style="color: #800080;">$event</span><span style="color: #000000;">);

</span><span style="color: #008000;">//</span><span style="color: #008000;">Use triggerEventUntil() for criteria-based short-circuiting:</span>
<span style="color: #800080;">$results</span> = <span style="color: #800080;">$events</span>->triggerEventUntil(<span style="color: #800080;">$callback</span>, <span style="color: #800080;">$event</span>);
ログイン後にコピー

上面的代码可以看到我们使用自定义事件类创建了一个事件对象,调用相关拦截器为事件对象设置属性。我们有了事件对象还是用trigger()触发事件吗?显然不是,我们使用triggerEvent($event)方法,该方法接收一个事件对象。而triggerEventUntil有一个回调函数,该回调函数作为是否进行短回路的依据。

 

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート