文档章节

一个活生生的Yii2事件例子

阿北2017
 阿北2017
发布于 2017/05/22 14:54
字数 1592
阅读 63
收藏 0
点赞 0
评论 0

相信上一节你一定看了观察者模式,我们现在开始说Yii2的事件,请大家用观察者的思维去看它。

为了让话题轻松一点,我们模拟一个场景,假设经理小X要北哥做一个登陆,登陆后还要做另一些事情:

  • 本地留一个log
  • 告诉登陆者的朋友它登陆了
  • 发送一个邮件给管理员

如何实现“另一些事情”那?他们将来要具有多变性,如何保证他们最小程度污染登陆逻辑那?

这时我突然想到了“耦合度最低、但是依然牛逼交互中的观察者模式”,话说我们自己又何尝不是那,白百合被小鲜肉摸了一下屁股而已,有人发朋友圈、有人发微博、有人发声明,观察者是真操碎了心。????

先来熟悉一下登陆的代码 app\controllers\UserController.php

class UserController extends Controller {
	
	public function actionIndex(){
		// 这里有一些代码.....
		Yii::$app->user->login($user);
		//	todo 登陆后要做的事情				
	}
}

没错,为了实现经理的需求,我必须用观察者实现这段逻辑,因为它具有很强的扩展性,能轻松应付小X经理多变的性格,随时增减登陆后的事情。

而Yii中有一个观察者的深度执行者,那就是事件机制

挖掘主题和观察者

首先我们要知道一切都是因为会员登陆,这就是主题。因此我们要为登陆起一个事件名字,对于事件我们喜欢用大写的常量标识,这就类似于js中的click、change这些关键词,它代表一些事情发生了。

根据观察者模式的原理,在 Yii::$app->user->login($user); 之前,我们需要订阅(事件的绑定),登陆后需要通知订阅者(事件触发)。

好,从需求看现在一共有三个观察者,我们暂时命名为

  • OLog 记录日志
  • Admin 给管理员发邮件
  • Friend 通知登陆者朋友

我们先来实现这些观察者

// OLog   app\models\OLog.php
class OLog {
	static public function add($event){
		echo "我记录了一条登陆记录";
	}
}
// Admin app\models\Admin.php
class Admin {
	static public function sendMail($event){
		echo "我给管理员发了邮件";
	}
}
// User app\models\User.php
class User {
	static public function notifyFirend($event){
		echo "告诉了朋友们我登陆了";
	}
}

上面三个类,我们实现了每个观察者自行的代码,你一定注意到了,这些方法通通有一个叫做$event的形参,它会将本次事件一些必要的参数传递给每个观察者的方法,本文后面会对其有讲解。

ok

观察者订阅主题(事件的绑定)

接下来我们要让三个观察者订阅登陆主题,就是事件中的绑定,它应该在登陆之前就完成。

为了实现方便,我决定在 UserController 的构造函数里做这个事情 app\controllers\UserController.php

class UserController extends Controller {
	
	//	定义事件名字
	const EVENT_USER_LOGIN = 'user_login';
	
	public function __construct(){
		//	绑定事件
		$this->on(self::EVENT_USER_LOGIN,['app\models\OLog','add']); 
		$this->on(self::EVENT_USER_LOGIN,['app\models\Admin','sendMail']); 
		$this->on(self::EVENT_USER_LOGIN,['app\models\User','notifyFirend']); 
	}
	
	public function actionIndex(){
		.....
		//	login				
	}
}

因为我知道Yii的 Component 类引入了Event事件,所有继承于Component的类都可以使用它,Controller继承了Component类。

我们可以通过

$this->on("事件名称","方法")

绑定一个方法到某个指定事件上,这个方法可以是一个全局的方法、一个类的静态方法、一个对象的方法,还能是一个匿名方法,这个后续会讲到。

本次我用的是类的静态方法。

ok,订阅(事件的绑定)完活。

主题通知观察者(事件的触发)

接下来就是等待,等待某个会员登陆后通知所有我们上面绑定的方法,那么如何通知那?这就是事件的触发,Yii已经为我们提供了方法。

app\controllers\UserController.php

class UserController extends Controller {
	
	//	定义事件名字
	const EVENT_USER_LOGIN = 'user_login';
	
	public function __construct(){
		//	绑定事件
		$this->on(self::EVENT_USER_LOGIN,['app\models\OLog','add']); 
		$this->on(self::EVENT_USER_LOGIN,['app\models\Admin','sendMail']); 
		$this->on(self::EVENT_USER_LOGIN,['app\models\User','notifyFirend']); 
	}
	
	public function actionIndex(){
		// 这里有一些代码.....
		Yii::$app->user->login($user);
		$this->trigger(self::EVENT_USER_LOGIN); 						
	}
}

没错,就是一句

$this->trigger(self::EVENT_USER_LOGIN); 	

它通知了所有绑定了该事件的方法,写日志的写日志,发邮件的发邮件。

事件成功应用于此。

完了么?

没完,你应该发现了,这个代码有一个问题,就是trigger函数的确告诉了所有的订阅者会员登陆了,但是,但是它没有告诉是哪个会员登陆了。。。。。

那观察者如何发邮件、如何群发好友、如何如何那?

还记得我们实现观察者类时候的那个形参么$event,我们知道它能接收一些事件相关信息,但是,是谁传递给他们的那?

这就要欢迎trigger的第二个参数出场了

// Component类中
public function trigger($name, Event $event = null)

我们可以传递一个事件类对象给触发函数,你可能有点蒙,简单点说就是Yii中有一个与事件紧密相关的 yii\base\Event 类,它封装了与事件相关的有关数据,并提供一些功能函数作为辅助。

我们可以自己定义事件类,继承于它就完事了。

开始吧,这个事件类能帮我把会员的ID传递给每个观察者。

现在我们在@app下建立一个events的文件夹,新建一个类叫做UserLoginEvent.php

// event/UserLoginEvent.php
namespace app\events;

use yii\base\Event;

class UserLoginEvent extends Event {

    public $userId = 0;
}

这样就完事了,现在我们重写触发函数。 app\controllers\UserController.php

use app\events\UserLoginEvent;

class UserController extends Controller {
	
	.......
	.......
	
	public function actionIndex(){
		// 这里有一些代码.....
		Yii::$app->user->login($user);
		
		$event = new UserLoginEvent();
		$event->userId = $user->id;
		
		$this->trigger(self::EVENT_USER_LOGIN,$event); 						
	}
}

这样$event对象就带着会员id飞鸽传书到每个订阅者方法中去了。

我们看看订阅者如何使用它那?

// User app\models\User.php
class User {
	static public function notifyFirend($event){
		$userId = $event->userId;
		echo "告诉了朋友们我登陆了";
	}
}

看明白了吧~

ok,到此我实现了小X经理的需求,开始提交代码了。

想知道小X经理看到后的结果么?等北哥下回分解。

© 著作权归作者所有

共有 人打赏支持
阿北2017
粉丝 61
博文 54
码字总数 68986
作品 0
洛阳
yii2批量添加的问题

作者:白狼 出处:http://www.manks.top/yii2batchinsert.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利...

白狼栈
2016/05/17
141
0
从配置文件的角度去了解Yii2

前言 Yii2是一个奇特的框架,其牺牲了现在盛行的解耦设计,用一个高度耦合的结构提供给开发者一个方便的几类抽象,Application,Module,Component,甚至是ServiceLocator.想让对象具备哪类特征就直...

Vett
2017/12/23
0
0
yii2项目实战之配置

作者:白狼 出处:http://www.manks.top/document/yii2-blog-config.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律...

白狼栈
2016/08/01
24
0
Yii2 实例管理

Yii2 实例管理 Yii2框架没有提供类似ZendFramework3中提供的ServiceManager.那么Yii2框架是如何管理对象实例的呢? 长时间使用Yii2框架的童鞋一定已经适应了对象中的public变量,以及一个来自y...

Vett
2017/12/23
0
0
yii2 - Behavior 实例及源码分析

Behavior 的简述 行为简单来说是组件的扩展,可以对组件的属性,方法,事件 (yii2组件的三大要点)进行扩展而无需改动组件现有的代码逻辑。即此行为所拥有的属性,方法,事件,都会被绑定它...

big_cat
2016/06/01
811
0
yii2学习——事件(event)

最近在学习Yii2,这里记录一下学习yii2的事件,一个简单的事件实例: 包括了一个对象、一个静态对象、一个匿名函数。 appcontrollerssiteController /** * 事件处理 */ public function act...

卖小女孩的小火柴
2015/05/05
0
5
Yii2框架图解

Yii2框架图解 Love冥天个人博客-关注IT|PHP|互联网|php个人博客交流2017-11-281 阅读 yii2Yii2 图片根据Yii类参考手册,Yii源代码,开发常用方法构成. 1.yii2 控制器类图 2.yii2 cookie 类图...

Love冥天个人博客-关注IT|PHP|互联网|php个人博客交流
2017/11/28
0
0
这些最热门的 PHP 框架,哪一款是你的菜?

原文出处:opensource 译文出处:开源中国—两味真火 PHP 是世界上最流行的编程语言之一,广泛用于主要的项目中。例如,Facebook 就是利用 PHP 来创建和维护他们的内部系统;WordPress 内部基...

opensource
2016/12/27
0
0
Yii2 源码分析 - 入口文件执行流程

以 yii 2.0.14 高级版的 frontend 为例,从 frontend/web/index.php 开始 入口文件看着就这么几行,简单的很,那他是怎么通过这几行来运行应用的呢?先看 Yii.php 内的逻辑 接下来,就是重头...

botkenni
05/03
0
0
yii2 - Event 实例及源码分析

yii2 可以方便的使用 Event 组件基类 来实现 注册事件和监听触发 机制,每个事件都有自身的事件队列 首先要知道,yii2的事件一共有三类:对象级,类级,全局 Yii::$app 级 对象和 全局是通过...

big_cat
2016/05/27
188
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CoreText进阶(七)-添加自定义View和对其

CoreText进阶(七)-添加自定义View和对其 其它文章: CoreText 入门(一)-文本绘制 CoreText入门(二)-绘制图片 CoreText进阶(三)-事件处理 CoreText进阶(四)-文字行数限制和显示更多...

aron1992
12分钟前
0
0
Python爬虫 爬取百合网的女人们和男人们

学Python也有段时间了,目前学到了Python的类。个人感觉Python的类不应称之为类,而应称之为数据类型,只是数据类型而已!只是数据类型而已!只是数据类型而已!重要的事情说三篇。 据书上说...

p柯西
23分钟前
0
0
在Java中,你真的会日期转换吗

1.什么是SimpleDateFormat 在java doc对SimpleDateFormat的解释如下: SimpleDateFormatis a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows fo......

Java小铺
32分钟前
0
0
Linux系统梳理---系统搭建(二):tomcat的安装和使用

上一章讲到JDK的安装使用,这一章主要记录下服务器tomcat的安装以及部署一个项目. 1.下载tomcat,这里下载的是apache-tomcat-8.5.32.tar.gz 2.创建文件夹,便于管理,和JDK一样,在usr目录下创建t...

勤奋的蚂蚁
42分钟前
0
0
ES15-聚合

1.Terms Aggregation 分组聚合 2.Filter Aggregation 过滤聚合

贾峰uk
43分钟前
0
0
【2018.07.19学习笔记】【linux高级知识 20.27-20.30】

20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行命令 20.30 expect脚本传递参数

lgsxp
46分钟前
0
0
10.32/10.33 rsync通过服务同步~10.35 screen工具

通过服务的方式同步要编辑配置文件:[root@linux-xl ~]# vim /etc/rsyncd.confport=873log file=/var/log/rsync.logpid file=/var/run/rsyncd.pidaddress=192.168.43.21[tes...

洗香香
49分钟前
0
0
与女儿谈商业模式 (3):沃尔玛的成功模式

分类:与女儿谈商业模式 | 标签: 经济学 沃尔玛 陈志武 2007-05-10 09:09阅读(11279)评论(30) 与女儿谈商业模式 (3):沃尔玛的成功模式 陈志武 /文 沃尔玛(Wal-Mart)是另一个有意思的财...

祖冲之
56分钟前
0
0
网页加载速度优化方法总结

1、减少请求 最大的性能漏洞就是一个页面需要发起几十个网络请求来获取诸如样式表、脚本或者图片这样的资源,这个在相对低带宽和高延迟的移动设备连接上来说影响更严重。 2、整合资源 对开发...

Jack088
今天
0
0
dubbo学习

https://blog.csdn.net/houshaolin/article/details/76408399

喵五郎
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部