前言
如果你是从实战的开篇一直看到这里,相信使用yii2做一些的基本的功能开发,对你来说应该是比较轻松了。那有些人就想要提高自身的技术能力,比方说开始研究源码,通读,熟悉底层架构的执行流程等等。下面我们就假设有些人的臆想,仅仅先做一个了解,后文会做具体分析。
比如从入口文件分析,调用了yii\base\Application(yii\web\Application继承该类)的run方法,该方法里面有如下两行代码看不懂啊,瞬间整个人都不好了。1
2$this->trigger(self::EVENT_BEFORE_REQUEST);
$this->trigger(self::EVENT_AFTER_REQUEST);
那先暂停,先不研究这个了,那就从增删改查开始研究吧。
以创建栏目为例(我们只看大概,不追究细节):
1、实例化 Category 模型
2、调用common\models\Category的load方法和save方法,实质是调用yii\base\Model的load方法和yii\db\BaseActiveRecord的save方法
3、那我来看看yii\db\BaseActiveRecord的save方法是怎么实现的
调用yii\db\ActiveRecord的insert方法->调用yii\db\ActiveRecord的insertInternal方法->调用yii\db\BaseActiveRecord的beforeSave方法…..
好嘛,研究不要紧,没看几处源码又看不下去了1
2
3
4
5
6
7public function beforeSave($insert)
{
$event = new ModelEvent;
$this->trigger($insert ? self::EVENT_BEFORE_INSERT : self::EVENT_BEFORE_UPDATE, $event);
return $event->isValid;
}
这都是什么鬼,实在看不下去了,心塞塞……
事件是什么?
事件,大家都不陌生。平时谁谁谁上新闻啦,哪哪个公司副总怎么滴怎么滴啦,这些都是事件。但是此事件非彼事件,相信各位平时接触的比较多的应该还是javascript里面的事件。比如说要给某DOM元素绑定一个事件,点击触发后会做出什么响应。注意我们在javascript里面实现的这个过程哦,我们是用on方法给某DOM元素绑定一个事件,即预先定义好一个事件;其次,事件触发后又是如何做出响应的呢?是不是为on方法写了一个回调函数进行处理的呢?光说不练不是我们的风格,来看一个js例子:1
$('#event').on('click', function () {});
上面正是为一个id=event的元素绑定了一个click点击事件,当我们点击id=event的元素后,会触发该事件,触发会做些什么呢?这就要看我们在上面的回调函数function怎么实现的了,整个流程上相信大家都是相当熟悉了。
当然,说了那么多,无非是想让大家对本文要说的重点“事件”的有一个基本的理解。
在yii2中,也是有事件这一概念的。具体怎么理解事件呢?其实你已经理解的差不多了,我们现在的问题重点是如何在yii2中使用事件!
事件的绑定
像js那样,可以通过on方法定义或者说是绑定一个事件。在yii2中,事件的绑定是通过yii\base\Component的on方法进行操作的,很显然,同js操作一样,我们在定义事件的同时,需要为其绑定一个回调函数,用于事件触发后需要做什么对不对?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<?php
namespace backend\controllers;
use Yii;
use yii\web\Controller;
/**
* 事件测试
* @see http://www.manks.top/document/yii2-event.html
*/
class EventTestController extends Controller
{
const EVENT_TEST = 'event_test';
public function init ()
{
parent::init();
$this->on(self::EVENT_TEST, function () {
echo "I`m a test event.";
});
}
}
代码看起来比js定义要多很多行,不要头晕目眩,我们来解释一下
1、上面说了,事件的绑定要调用 yii\base\Component的on方法,为啥这里调用的是yii\web\Controller的on方法呢?聪明的同学肯定想到了,yii\web\Controller类继承yii\base\Component类,确实如此,追踪下源码便会发现,yii\web\Controller继承yii\base\Controller,yii\base\Controller继承 yii\base\Component
2、on方法的第一个参数是事件名,事件名为啥用常量标识?如果仅仅看定义事件的话,可能看不出来多大的优势,等看完这篇文章你自然明白了
3、关于回调函数的写法,我们这里给出了一个最简单的写法,直接写一个function即可,但是有时候这个回调函数可能要处理的业务逻辑非常多,代码都写在init方法里是不是就不便于维护了?我们再介绍两种比较常用的写法供大家参考:1
2
3
4
5// 调用当前类的onEventTest方法
$this->on(self::EVENT_TEST, [$this, 'onEventTest']);
// 调用backend\components\event\Event类的test方法
$this->on(self::EVENT_TEST, ['backend\components\event\Event', 'test']);
4、需要提醒的是,继承类EventTestController的init方法最好调用下parent::init()方法
我们在上述事件绑定的方法中定义了一个名为event_test的事件,名字可以随便定义,不过最好见名知意!相信我不说你也能明白,如果这个事件被触发了,会执行程序1
echo "I`m a test event.";
但是,如何触发?这是我们下面要关心的问题。
事件的触发
如果一个事件只有定义,但是却没有被触发,那这个事件要之何用?事件的触发也很简单,只需要调用 yii\base\Component类的trigger方法,指定事件名即可,来看下我们如何调用EventTestController::EVENT_TEST事件1
2
3
4public function actionIndex ()
{
$this->trigger(self::EVENT_TEST);
}
简单吧。我们访问下index.php?r=event-test/index,发现页面上果然输出了 I`m a test event.
关于事件,先说到这里,你明白如何定义,如何触发了吗?至于文中开头介绍的问题,我们后面专门写一篇具有实战性的文章来进行阐述。
为了趁热打铁,下一节我们借助事件来实现邮件的发送。等不及的小伙伴可以选择手动尝试哦