常用底层知识 - 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的代码

  • 扩展阅读:深入理解Yii2.0 » Yii 基础 » 行为(Behavior)

  • 行为的使用场景

    比如给用户加一些会员功能,下面是伪代码:

    $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类里获取这个功能就行

    这就是装饰模式的作用体现之一,本来不需要某些少用的功能的,那就单纯地做自己的事好了,也不用加载更多东西,当需要那个功能时,再把这个功能装饰到自身来强化自己