Rudy 2017-04-26 15:08:36 2598次浏览 1条回复 2 2 0

最近找工作中,由于之前项目都是用Yii2,但后来发现自己对它只会做CRUD常见操作,除此之外什么都不了解。

所以打算趁着机会看一遍Yii2源码,分享自己的一点见解。

例子

假如你是一名保姆,你每天都会被主人安排工作,例如:

#9:00你要搞卫生还有买菜
clean();
buy();

#当然9:00后你干完活可以自由活动比如看电视
watch();

#12:00你要负责做饭
cook();

当然工作是变动的,例如主人今天不想你在9:00的时候搞卫生,把搞卫生移到做完饭后才进行也是完全没问题的,谁让他是你的master。

主人之前每天的任务是负责监督你,但是现在每天早上都要出去工作了,没办法每天准时安排你工作,所以在他出门前会列出一张任务清单给你,上面会安排你在几点做什么事,例如:

$list = [
    '9:00'=>[
        'clean',
        'bug'
    ],
    '12:00'=>[
        'cook'
    ]
]

那你现在需要按照主人的安排来做事:

#由于同一时间内可能存在很多事情要做,所以我们需要进行for循环,然后把任务一件一件完成

#9:00时
foreach($list['9:00'] as $value) {
    $value();
}

#空闲时间
watch();

#12:00时
foreach($list['12:00'] as $value) {
    $value();
}

从代码角度上来看,我们可以把foreach封装成一个函数,所以现在变成:

function work($time){
    global $list;
    foreach($list[$time] as $value) {
        $value();
    }
}

#9:00要做的事
work('9:00');

#空闲时间
watch();

#12:00要做的事
work('12:00');

但是今天主人打电话回来跟你说:

“哎呀,菜我已经买了,所以9:00的时候你就不要去买菜了”

“然后做完饭我们一起出去散步吧!”

其实这无非就是主人对你的任务清单做了一个增加或者删除的动作:

#给任务清单加任务
function add($time,$event){
    global $list;
    $list[$time][] = $event;
}

#给任务清单减任务
function remove($time,$event){
    global $list;
    unset($list[$time][array_search($event,$list[$time])]);
}

现在我整天的流程变成了这样:

#主人在9:00前让我不要买菜
remove('9:00','buy');

#我在9:00要做的事
work('9:00');

#主人让我在9:00的时候不要去搞卫生
#但是没办法啊主人。。
#9:00已经过了我已经搞完卫生了。。
remove('9:00','clean');

#空闲时间可以看电视
watch();

#主人在12:00前说做完饭去散步
add('12:00','walk');

#我在12:00要做的事
work('12:00');

回到Yii2

写到这边,其实已经描述了Yii中事件的大概,说到底就是两点:

1.对任务清单做增删操作

2.在程序流程中事先埋好几个执行点,流程到执行点时会自动执行对应任务清单里的事件

代入保姆的案例,再来看看Yii中的源码:

#9:00时要做的事(处理请求前要做的事)
$this->trigger(self::EVENT_BEFORE_REQUEST);

#空闲时间看电视
$response = $this->handleRequest($this->getRequest());

#12:00时要做的事(处理完请求后要做的事)
$this->trigger(self::EVENT_AFTER_REQUEST);

我想在每个用户处理完请求后发送邮件给自己,可以这样做:

#处理请求
$response = $this->handleRequest($this->getRequest());

#往对应的任务清单里添加“发送邮件”这一件事,告诉它处理完请求后一定要发邮件
#此处的on()相当于案例中的add()
#另外,off()相当于案例中的remove()
$this->on(self::EVENT_AFTER_REQUEST,'sendmail')

#处理请求后要做的事
$this->trigger(self::EVENT_AFTER_REQUEST);

当然一般情况下,这种做法会修改到程序源码,所以我们一般在controller或者model中调用`Yii::$app->on()或Yii::$app->off()`进行事件的添加和删除。

可能你会有疑问:

1.如果我想在处理请求之前添加事件怎么办?
2.那个任务清单,即案例中的$list在哪

关于事件其实还有很多可以说,但由于只是简单聊聊,所以就不说太多了,具体的代码可以看` Component和Event` 这两个类。

觉得很赞
您需要登录后才可以回复。登录 | 立即注册