常用底层知识 - 了解一下组件

  • 作者:KK

  • 发表日期:2016.12.8


组件有什么用

Yii总是强调自己是一个基于组件的框架,所以组件这个概念是很重要的,我这么久才讲组件好像有点对不起Yii了~


笼统地说,一切代码里关于Yii::$app->xxx的app的属性,如果这个属性是一个object,那你基本上可以理解为组件,比如:

Yii::$app->request

Yii::$app->response

Yii::$app->user

Yii::$app->log

Yii::$app->db

撇开Yii自身的概念先不说,在常规的应用实现里,我们通常都需要一些由始至终只提供一个实例的单例对象,最经典的莫过于Db类

因为咱们都不希望每做一次SQL查询都new一个Db类,那可多累呀,其实最初我们想到的做法就是在项目初始化的时候只要new一下放到全局数组里,后面直接访问这个new过的Db类就可以了嘛,好了这个其实大家都清楚

这些东西我们在通俗的角度可以理解为一个单例对象,不需要再new另一个实例,它提供了一种贯穿整个执行周期的功能服务(搜索关键词:设计模式 单例模式

了解Linux系统的朋友你可以认为它相当系统里的service就对了,不可能每次使用mysql都来一次service mysqld start,只要开机启动时自动运行一次这个命令,以后都能调用这个数据库服务了

这种东西在Yii里的概念就叫做组件


组件的配置

如果说在配置里第一层key中的basePath就是控制Yii::$app->basePath的话

那么要配置db组件是不是就像下面这样写配置呢?

return [
	'id' => 'APP的ID',
	'basePath' => '...',
	'db' => 写点什么

其实不对的,因为db组件不是yii\web\Application的属性,所以不能这么玩

一个应用其实可以不需要db组件的,所以对于$app来说它更不是必须存在的属性


通过components属性来定义组件

Yii让我们在配置文件的components这个key里定义组件,所以你在应用模板部署好的配置文件里可以看到这些:

大家都是具备正常智商的人吧,我就不像官方文档那样正式地解释这些了,一看就懂的嘛

而你要注意的是,如果你把db这个key给删除了,那访问Yii::$app->db就会报错,因为没有装载db组件

再打个生动点的比方,组件就像武器一样,Yii::$app可以通过components的配置来装载、卸载不同的武器来强化整个$app


组件ID

组件ID其实就是Yii::$app->组件ID这一部分,这个ID是根据components配置的key来确定的,key叫什么,ID就叫什么

一般大家交流时说“user组件”那其实指的就是Yii::$app->user这个user(组件ID)


核心组件

可为什么有的组件配置并不包含class这个key

比如reqeust这个组件,你应该注意到它的定义是这样的:

'components' => [
	'request' => [
		'cookieValidationKey' => '121212',
	],
	...
]

明显配置只指定了cookieValidationKey这个属性值为121212,那底层Yii::createObject的时候怎么知道去new哪个类呢?

其实Yii底层已经预定义了request组件的class为“yii\web\Request”这个类了

因为这是“请求组件”嘛,框架肯定要处理请求信息,所以这是必须的组件,人家定义概念为“核心组件”,不管你在web.php里是否要填写其它request组件的配置,反正底层已经预配置了class

  • 进一步了解:

    建议你执行print_r(Yii::$app->coreComponents());或者去看看@vendor/yiisoft/yii/web/Application.php文件里的public function coreComponents()这部分代码你就懂了


组件只在首次调用时实例化

我相信多数同学都玩过TP框架,D函数M函数……

比如在第一次访问Yii::$app->db时,Yii会判断db组件是否已经有保存在某个地方,有的话就不再new了,直接从这个地方取得db组件的实例进行返回


结语

组件很重要,平时写程序动不动就要用到组件,特别是控制器、表单模型这些地方,还有就是自己写的扩展类多数也要用

你把思维转换成这样吧:以前你写的其他PHP项目经常在哪里调用全局对象,那在Yii也就经常在什么场合调用组件了


由于配置文件实质上是对各个类的属性值进行设置,再让类根据这些属性的值来做具体的相关工作

所以关于Yii的配置解释,你可能在官方文档中找不到太专门的解释文章,因为类的属性就对应了配置的key,类的属性注释就是配置的使用说明,爱控制哪个类/组件的工作方式就通过配置注入哪个属性吧


预启动组件

平时只要不调用组件,它就不会初始化,但是可以通过预启动配置来让它提前在APP初始化的时候也自动初始化,做法就是配置app的bootstrap属性

在一般常见的项目里,我们往往只需要预启动log组件就可以,不需要刻意去添加其它组件进行预启动,不然可能还一直用不到嘛


附:常见组件介绍(包括非核心的)

  • reqeust: 请求组件

    主要负责提供请求相关的信息数据,调用urlManager组件实现解析URL到控制器方法,请求Cookie的校验读取,csrf攻击的防御


  • urlManager: URL管理组件

    负责解析URL,它返回的值会告诉你:当前请求的URL想调用哪个模块的哪个控制器的哪个方法


  • view: 视图组件

    负责渲染视图,并返回HTML字符串

    其中提供了各种视图定位方法、layout支持和视图小部件支持等等


  • response: 响应组件

    主要负责将header和数据发送给客户端,还有cookie也是

    并提供了重定向、发文件(提供下载)、响应图片音频视频等字节流的便捷方法,
    还可以自定义响应数据序列化的格式

  • db: 数据库组件

    虽然常见但实际上平时写代码反而不多用这个组件,我们更多是使用yii\db\ActiveRecord和yii\db\Query这些类,它们的底层会自动调用db组件做事

    还包括读写分离、数据库事务的控制,反正数据库有关的事你找它的相关文档看用法就是


  • cache: 缓存组件

    感觉没啥好说的了,缓存相关就用它吧,这个我暂时不打算写文章,学会基本的框架使用后,自己去看官网的文档


  • user: 用户组件

    这个组件非常抽象,抽象到都不关心你数据库中的user表是怎么设计的。它就是用户而不是用户数据

    通俗地说我们最常用这个组件去管登陆访问授权相关的事情,也会通过这个组件获取当前用户对应数据表里的信息
    ---
  • log: 日志组件

    我们基本上并不调用这个组件,反而是经常接触它的配置设定或者用于扩展日志功能

    平时只要在这个组件的配置里写点东西就能让框架按照我们的意思产生指定的日志,包括日志文件名和大小(超出大小分自动开设新日志等),又或者重要日志可以实现邮件通知