概念理解:在某一个事件(trigger)发生的时候,触发预先设定(on)的代码,这是代码解耦的一种方式。
绑定事件、触发事件的类继承的是Component
,只在当前示例中运行,不与类的其余实例发生关系,也不与其余类、其余实例发生关系。php
代码示例: <?php namespace common\components; use yii\base\Component; class EventTest extends Component { const EVENT_SAY_HELLO = 'say_hello'; public function sayHello($event) { echo $event->data; $event->handled = true; } public function sayWorld($event) { echo $event->data; } } 1.绑定事件: $event = new EventTest(); $event->on(EventTest::EVENT_SAY_HELLO, [$event, 'sayHello'], 'Hello!'); $event->on(EventTest::EVENT_SAY_HELLO, [$event, 'sayWorld'], 'World!'); 2.解除事件: $event->off(EventTest::EVENT_SAY_HELLO, [$event, 'sayHello']); 3.触发事件: $event->trigger( EventTest::EVENT_SAY_HELLO);
绑定事件、触发事件的类继承的是Event
,类级别事件会被类自身、类的实例、后代类、后代类实例的同一事件所触发,影响范围更大html
代码示例: <?php namespace common\components; use yii\base\Event; class EventTest extends Event { const EVENT_SAY_HELLO = 'say_hello'; public function sayHello($event) { echo $event->data; } public function sayWorld($event) { echo $event->data; } } 1.绑定事件: $event = new EventTest(); $event->on('\common\components\EventTest', EventTest::EVENT_SAY_HELLO, [$event, 'sayHello'], 'Hello!'); $event->on('\common\components\EventTest', EventTest::EVENT_SAY_HELLO, [$event, 'sayWorld'], 'World!'); 2.解除事件: $event->off('\common\components\EventTest', EventTest::EVENT_SAY_HELLO, [$event, 'sayWorld']); 3.触发事件: $event->trigger('\common\components\EventTest', EventTest::EVENT_SAY_HELLO); 类级别参数比实例级别多一个参数:类名
注意: 解除事件若是不传 handle,则会解除该事件下的全部 handle。 在其中一个 handle 里面加上 $event->handled = true 也会阻止后续 handle 的触发,如上代码。
利用Application
实例在整个应用的生命周期中全局可访问的特性,来实现这个全局事件的。在任意须要的时候,均可以触发全局事件,也能够在任意必要的时候绑定,或解除一个事件。数组
代码示例: 1.绑定事件: $event = new EventTest(); Yii::$app->on('global_event', [$event, 'globalEvent'], 'global event'); 2.触发事件: Yii::$app->trigger('global_event'); 全局级别实际上也是一个特殊的实例。[注意所谓全局其实做用范围也只是在当前请求的生命周期有效,而非当前会话(简单的说,打开浏览器,访问服务器,直到浏览器关闭,称为一次会话)]
实例级别经过维护Component
类的属性 $_events
数组,触发事件时经过[事件名称]取到[当前实例]的handle
数据,再经过函数call_user_func
触发handle
。浏览器
类级别经过维护Event
类的属性 $_events
数组,触发事件时经过[类名和事件名称]取到[当前类以及父类]的handle
数据,再经过函数call_user_func
触发handle
。服务器
Component 的 $_event
数据结构示例以下数据结构
Array ( [say_hello] => Array ( [0] => Array ( [0] => Array ( [0] => common\components\EventTest Object ( [_events:yii\base\Component:private] => Array *RECURSION* [_eventWildcards:yii\base\Component:private] => Array ( ) [_behaviors:yii\base\Component:private] => Array ( ) ) [1] => say_hello ) [1] => Hello! ) ) )
以上总结参考了深刻理解Yii2.0,其实之前就看过,可是也只是局限于看过,没有本身跑demo调试、查看源代码,而后就误觉得本身明白了,其实过俩天什么都不记得了。因此如今经过写博客来加深本身的理解,这篇博客其实主要讲的仍是事件的使用,具体原理一带而过,若是有小伙伴只知其一;不知其二,可能查看一下源代码[yii\base\Component yii\base\Event
]你就明白了。因为水平有限,欢迎小伙伴交流和指正。app