ホームページ > バックエンド開発 > PHPチュートリアル > PHP の Yii フレームワークのイベント メカニズムの詳細な分析、yiievent_PHP チュートリアル

PHP の Yii フレームワークのイベント メカニズムの詳細な分析、yiievent_PHP チュートリアル

WBOY
リリース: 2016-07-12 08:56:49
オリジナル
972 人が閲覧しました

PHP の Yii フレームワーク、yiievent のイベント メカニズムの詳細な分析

event
イベントは、既存のコードの特定の実行ポイントにカスタム コードを「挿入」できます。カスタム コードをイベントにアタッチすると、イベントがトリガーされたときにコードが自動的に実行されます。たとえば、メーラー オブジェクトがメッセージの送信に成功したときに、messageSent イベントを発生させることができます。正常に送信されたメッセージを追跡したい場合は、対応する追跡コードを messageSent イベントに添付できます。
Yii では、イベントをサポートするために yiibaseComponent と呼ばれる基本クラスが導入されています。クラスがイベントをトリガーする必要がある場合は、yiibaseComponent またはそのサブクラスを継承する必要があります。

Yiiのイベントメカニズム
YII のイベント メカニズムは、そのユニークな機能です。イベント メカニズムを適切に使用すると、さまざまなコンポーネント間の結合が緩和され、グループでの共同開発に役立ちます。
イベントを使用する必要がある場合、イベント処理関数をイベントにバインドする方法、およびイベントをトリガーする方法は他の言語とはまったく異なります。たとえば、JavaScript では
を使用できます。

リーリー

メソッドは、DOM 要素に処理関数をバインドします。DOM 要素上で指定されたイベント (クリックなど) が発生すると、設定された関数が自動的に実行されます。
ただし、PHP はサーバー側のスクリプト言語であるため、JavaScript と比較してイベントを自動的にトリガーすることができません。したがって、YII のイベントは手動でトリガーする必要があります。一般に、YII コンポーネントのイベント メカニズムを実装するには、次の手順が必要です:

イベント名を定義します。実際、レベルコンポーネントは on で始まるメソッドを定義し、その中のコードは次のように固定されています。 リーリー

つまり、関数名とイベント名は一致しています。このステップの目的は、このイベントにバインドされた処理関数を 1 つずつ実行することです。この一連のポッドキャストを書くのは一種の仕上げなので、さらに詳しく書いて、raiseEvent メソッドのコードを投稿します。


リーリー

イベントハンドラー

イベント ハンドラーは、関連付けられたイベントがトリガーされたときに実行される PHP コールバック関数です。次のコールバック関数のいずれかを使用できます:

    文字列形式で指定された PHP グローバル関数 ('trim' など)
  • [$object, $method] など、オブジェクト名とメソッド名の配列形式で指定されたオブジェクト メソッド;
  • [$class, $method] などのクラス名とメソッド名の配列形式で指定された静的クラスメソッド;
  • function ($event) { ... } などの匿名関数。
イベントハンドラーの形式は次のとおりです:

リーリー

$event パラメーターを通じて、イベント ハンドラーはイベントに関する次の情報を取得します。

    yiibaseEvent::name: イベント名
  • yiibaseEvent::sender:trigger()メソッドを呼び出すオブジェクト
  • yiibaseEvent::data: イベント ハンドラーをアタッチするときに渡されるデータ。デフォルトは空です。詳細は以下で説明します

追加のイベントハンドラー

yiibaseComponent::on() メソッドを呼び出して、イベントにハンドラーをアタッチします。例:

リーリー

イベントハンドラーの順序

1 つ以上のハンドラーをイベントにアタッチできます。イベントがトリガーされると、アタッチされたハンドラーがアタッチされた順序で呼び出されます。プロセッサが後続のプロセッサ呼び出しを停止する必要がある場合は、次のように $event パラメータの [yiibaseEvent::handled]] 属性を true に設定できます。 リーリー

デフォルトでは、新しくアタッチされたイベント ハンドラーは既存のハンドラー キューの最後に配置されます。したがって、このハンドラーは、イベントが発生したときに最後に呼び出されます。プロセッサ キューの先頭に新しいプロセッサを挿入すると、そのプロセッサが最初に呼び出されます。これを実現するには、4 番目のパラメータ $append を false として渡し、 yiibaseComponent::on() メソッドを呼び出します。 リーリー

トリガーイベント


イベントは yiibaseComponent::trigger() メソッドを呼び出すことによってトリガーされます。このメソッドはイベント名とイベント オブジェクトを渡してイベント ハンドラーにパラメーターを渡す必要があります。例:
リーリー

上記のコードが bar() を呼び出すと、hello という名前のイベントがトリガーされます。

ヒント: イベント名を表すにはクラス定数を使用することをお勧めします。上記の例では、定数 EVENT_HELLO を使用して hello を表しています。これには 2 つの利点があります。まず、タイプミスを防止し、IDE のオートコンプリートをサポートします。次に、定数の宣言を調べるだけで、クラスがどのイベントをサポートしているかを知ることができます。

イベントがトリガーされたときに、追加情報をイベント ハンドラーに渡したい場合があります。たとえば、メール プログラムは、どのメッセージが送信されたかをハンドラーが認識できるように、メッセージ情報を messageSent イベントのハンドラーに渡す必要があります。これを行うには、yiibaseComponent::trigger() メソッドの 2 番目のパラメーターとしてイベント オブジェクトを指定できます。このイベント オブジェクトは、yiibaseEvent クラスまたはそのサブクラスのインスタンスである必要があります。例:

リーリー

yiibaseComponent::trigger() メソッドが呼び出されると、名前付きイベント (トリガー メソッドの最初のパラメーター) にアタッチされたすべてのイベント ハンドラーが呼び出されます。

イベントハンドラーを削除

イベントからハンドラーを削除するには、yiibaseComponent::off() メソッドを呼び出します。例: リーリー

通常、イベントにアタッチされた匿名関数は、どこかに保存しない限り、削除しないでください。上記の例では、匿名関数が変数 $anonymousFunction として格納されていると仮定しています。

移除事件的全部处理器,简单调用 yii\base\Component::off() 即可,不需要第二个参数:

$foo->off(Foo::EVENT_HELLO);
ログイン後にコピー

类级别的事件处理器

以上部分,我们叙述了在实例级别如何附加处理器到事件。有时想要一个类的所有实例而不是一个指定的实例都响应一个被触发的事件,并不是一个个附加事件处理器到每个实例,而是通过调用静态方法 yii\base\Event::on() 在类级别附加处理器。

例如,活动记录对象要在每次往数据库新增一条新记录时触发一个 yii\db\BaseActiveRecord::EVENT_AFTER_INSERT 事件。要追踪每个活动记录对象的新增记录完成情况,应如下写代码:

use Yii;
use yii\base\Event;
use yii\db\ActiveRecord;

Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
  Yii::trace(get_class($event->sender) . ' is inserted');
});

ログイン後にコピー

每当 yii\db\BaseActiveRecord 或其子类的实例触发 yii\db\BaseActiveRecord::EVENT_AFTER_INSERT 事件时,这个事件处理器都会执行。在这个处理器中,可以通过 $event->sender 获取触发事件的对象。

当对象触发事件时,它首先调用实例级别的处理器,然后才会调用类级别处理器。

可调用静态方法yii\base\Event::trigger()来触发一个类级别事件。类级别事件不与特定对象相关联。因此,它只会引起类级别事件处理器的调用。如:

use yii\base\Event;

Event::on(Foo::className(), Foo::EVENT_HELLO, function ($event) {
  echo $event->sender; // 显示 "app\models\Foo"
});

Event::trigger(Foo::className(), Foo::EVENT_HELLO);

ログイン後にコピー

注意这种情况下 $event->sender 指向触发事件的类名而不是对象实例。

注意:因为类级别的处理器响应类和其子类的所有实例触发的事件,必须谨慎使用,尤其是底层的基类,如 yii\base\Object。
移除类级别的事件处理器只需调用yii\base\Event::off(),如:

// 移除 $handler
Event::off(Foo::className(), Foo::EVENT_HELLO, $handler);

// 移除 Foo::EVENT_HELLO 事件的全部处理器
Event::off(Foo::className(), Foo::EVENT_HELLO);

ログイン後にコピー

全局事件

所谓全局事件实际上是一个基于以上叙述的事件机制的戏法。它需要一个全局可访问的单例,如应用实例。

事件触发者不调用其自身的 trigger() 方法,而是调用单例的 trigger() 方法来触发全局事件。类似地,事件处理器被附加到单例的事件。如:

use Yii;
use yii\base\Event;
use app\components\Foo;

Yii::$app->on('bar', function ($event) {
  echo get_class($event->sender); // 显示 "app\components\Foo"
});

Yii::$app->trigger('bar', new Event(['sender' => new Foo]));

ログイン後にコピー

全局事件的一个好处是当附加处理器到一个对象要触发的事件时,不需要产生该对象。相反,处理器附加和事件触发都通过单例(如应用实例)完成。

然而,因为全局事件的命名空间由各方共享,应合理命名全局事件,如引入一些命名空间(例:"frontend.mail.sent", "backend.mail.sent")。

给组件对象绑定事件处理函数

$component->attachEventHandler($name, $handler);
$component->onBeginRequest = $handler ;
ログイン後にコピー

yii支持一个事件绑定多个回调函数,上述的两个方法都会在已有的事件上增加新的回调函数,而不会覆盖已有回调函数。
$handler即是一个PHP回调函数,关于回调函数的形式,本文的最后会附带说明。如CLogRouter组件的init事件中,有以下代码:

Yii::app()->attachEventHandler('onEndRequest',array($this,'processLogs'));
ログイン後にコピー

这就是给CApplication对象的onEndRequest绑定了CLogRouter::processLogs()回调函数。而CApplication组件确实存在名为onEndRequest的方法(即onEndRequest事件),它之中的代码就是激活了相应的回调函数,即CLogRouter::processLogs()方法。所以从这里可以得出,日志的记录其实是发生在CApplication组件的正常退出时。

在需要触发事件的时候,直接激活组件的事件,即调用事件即可,如:比如CApplication组件的run方法中:

if($this->hasEventHandler('onBeginRequest'))
  $this->onBeginRequest(new CEvent($this));
ログイン後にコピー

这样即触发了事件处理函数。如果没有第一行的判断,那么在调试模式下(YII_DEBUG常量被定义为true),会抛出异常,而在非调试模式下(YII_DEBUG常量定义为false或没有定义YII_DEBUG常量),则不会产生任何异常。
回调函数的形式:

普通全局函数(内置的或用户自定义的)

call_user_func(‘print', $str);

ログイン後にコピー

类的静态方法,使用数组形式传递

call_user_func(array(‘className', ‘print'), $str );

ログイン後にコピー

对象方法,使用数组形式传递

$obj = new className();
call_user_func(array($obj, ‘print'), $str );

ログイン後にコピー

匿名方法,类似javascript的匿名函数

call_user_func(function($i){echo $i++;},4);
ログイン後にコピー

或使用以下形式:

$s = function($i) {
  echo $i++;
};
call_user_func($s,4);
ログイン後にコピー

总结

关于Yii的事件机制其实就是提供了一种用于解耦的方式,在需要调用event的地方之前,只要你提供了事件的实现并注册在之后的地方需要的时候即可调用。

您可能感兴趣的文章:

  • PHP的Yii框架中移除组件所绑定的行为的方法
  • PHP的Yii框架中行为的定义与绑定方法讲解
  • 详解在PHP的Yii框架中使用行为Behaviors的方法
  • 深入讲解PHP的Yii框架中的属性(Property)
  • PHP的Yii框架中使用数据库的配置和SQL操作实例教程
  • 全面解读PHP的Yii框架中的日志功能
  • Yii使用find findAll查找出指定字段的实现方法
  • 解析yii数据库的增删查改
  • Yii PHP Framework实用入门教程(详细介绍)
  • 详解PHP的Yii框架中组件行为的属性注入和方法注入

www.bkjia.com本当http://www.bkjia.com/PHPjc/1111325.html技術記事 PHP の Yii フレームワークのイベント メカニズムを詳細に分析すると、Yiievent イベントは既存のコードの特定の実行ポイントにカスタム コードを「挿入」できます。カスタム コードを何かに添付します...
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート