常用底层知识 - Component 组件类的特性 ¶
作者:KK
发表日期:2016.12.08
组件类就是yii\base\Component这货,它是yii\base\Object的加强版
你可以这么认为:Yii让功能不是很丰富的类继承了Object,而让功能丰富的类继承了Component
特性1:包含 yii\base\Object 的所有特性 ¶
Object能做的,Component当然也能做到!
特性2:事件,这个很重要 ¶
这其实和js、nodejs里的事件是一样的道理,先搞个类测试一下:
namespace app;
class Game extends \yii\base\Component{
public $name = '小军吃瓜';
public function recharge($money){
//模拟充值
$db = ['table_order' => []];
$db['table_order'][] = [
'id' => count($db['table_order']),
'money' => $money,
];
//$db->save什么的我当然是乱写的啦,下面是重点
$this->trigger('createPayOrder'); //触发一个叫createPayOrder的事件,其实createPayOrder这部分名字自己随便起都可以
//后续的其它代码处理
//其实上面trigger时还能获取创建后的订单号,但这个要深入到yii\base\Event类 暂时不讲
}
}
再来控制器的测试代码:
$payMode = 'wechat'; //支付方式自己模拟
$game = new \app\Game();
if($payMode == 'alipay'){
$game->on('createPayOrder', function(\yii\base\Event $event){
//创建支付宝的支付订单
});
}elseif($payMode == 'wechat'){
$game->on('createPayOrder', function(\yii\base\Event $event){
//创建微信的支付订单
});
}//elseif(更多支付方式){}
$game->recharge(999);
这样就可以不修改Game类的情况下,只修改控制器的支付方式实现具体的支付订单创建了
少数程序员可能会觉得这个事件没啥卵用,其实这是一种编程经验不丰富的体现,不多辩驳,再过几年他反而会变得挺认可的
Yii框架里N多事件,未来调试一些深度问题偶尔还是要看源代码的,那想看懂它的源代码你肯定要懂事件,今天不懂先留个印象,改天有空回来再尝试学习一下!
也包括自己要扩展框架功能什么的,不会事件就不会扩展好多东西了,其实有很多事情是可以不用修改框架代码,直接用事件来插入自定义的工作内容就行
事件的触发者 ¶
在上面代码中
$game->on('createPayOrder', function(\yii\base\Event $event){ //xxxx });
这里回调函数有个参数叫
$event
,我们可以通过$event->sender
来访问到触发者,这个触发者就是Game类里$this->trigger
时的$this
,也就是Game类的实例本身echo $event->sender->name
就能取得Game类的name属性
还有更多事件的知识就先不讲了,晚点~
特性3:行为(可以动态添加方法属性
) ¶
听上去很逆天啊!这个特性可以让你的类没有A方法时,动态添加A方法,没有B属性也能动态添加B属性
或者换个说法,它让两个类合并成一个类了,这个新的类拥有两个类的方法和属性
但是这个特性普通程序员开发中通常都不会用到,熟练的程序员理解后可能会适当使用,反正不经常用,你急着学完框架做点东西就跳过这个特性先别学吧,其实我这里也不做专门细说
它是运用了设计模式里的装饰模式
思想来设计实现的
要尝试这个行为
特性就请在下载安装文章里下载我共享的应用模板,然后你运行?r=test/test-behavior
这个路由看看效果,也看看相关action的代码
行为的使用场景 ¶
比如给用户加一些会员功能,下面是伪代码:
$user = Yii::$app->user; $vip功能$user->vip == 2){ $vip功能//VIP2,下载网速1000KB/s }else($user->vip == 3){ $vip功能//VIP3,下载网速2000KB/s } if($vip功能$user->attachBehavior('vip', $vip功能$user->hasMethod('download')){ throw new \Exception('抱歉,您还没获得下载特权!请先充值VIP2以上会员资格哦!'); } $user->download('http://xx.com/a.zip', '/path/to/save.zip');
这里download方法当然是各个Vip类根据自己的功能特性去定义并返回相同类型的值了,其实user类很单纯的就是user,并不需要定义download方法,用到download功能的时候再从Vip类里获取这个功能就行
这就是装饰模式的作用体现之一,本来不需要某些少用的功能的,那就单纯地做自己的事好了,也不用加载更多东西,当需要那个功能时,再把这个功能装饰到自身来强化自己