常用底层知识 - 加载一个类

  • 作者:KK

  • 发表日期:2016.12.9


大概原理

Yii使用了psr-4的标准来加载class,所以没有被new过的class,相关的文件不会被include(你管它整个包有多少MB呢,反正没用的就不会被include,只占磁盘容量,不占内存)

先来看看这个别名的解析结果:

echo Yii::getAlias('@yii/log/FileTarget.php');

结果应该是类似我这样的:E:\projects\yii-demo\vendor\yiisoft\yii2/log/FileTarget.php

所以你应该发现了,当我们new \yii\log\FileTarget()的时候,Yii底层先把命名空间里面yii这一段当作@yii以别名来解析,得到了@yii的路径

再跟后面的/log/FileTarget.php拼接起来就成了整个类的路径

深入的加载原理文章请见《Yii的类自动加载机制


示例详解

先确认一下echo Yii::getAlias('@app');其实指的就是当前的项目目录吧

所以echo Yii::getAlias('@app/MySql.php');就会变成类似这样:E:\projects\yii-demo\MySql.php

好,关键词“app\MySql”,我们就试下添加这个类吧,

平时我们用标准的语言来描述这个类的名称,其实不能说它叫“MySql”类,而是要把命名空间也附上,所以是“app\MySql

这样才是它的完整类名,不然如果bpp命名空间下也有个MySql,谁知道你说的MySql是指app\MySql还是bpp\MySql呢?

好了请在@app目录下加个MySql.php,代码如下:

namespace app;

class MySql{
	public $dsn = '123';
}

这里要注意,通常情况下namespace的第一层都跟别名的名称完全对应(只是通常情况)

既然@app解析到了项目的目录,那MySql这个类处于项目目录下的话,我们就这么说吧:它也处于app命名空间下

接下来在控制器里测试测试:

$mysql = new \app\MySql();
echo $mysql->dsn;

如无意外就会输出123


别名目录的子目录增加类

我所谓的别名目录,就是指@app解析成的项目根目录,@vendor解析成的vendor目录,还有@yii的……

如果在这些目录的子目录添加class,则类的命名空间应该是这样写的:namespace 别名\子目录名称;

比如在@app的models目录增加一个类,那这个类的namespace就是app\models,很好理解了对吧

其实就算models里面再来个user子目录,那里面的类的命名空间也就是app\models\user


变通一点,有些菜鸟不要把眼光定格于“框架应用自带的目录”

其实自己也可以创建自定义名字的目录添加class而不需要添加任何配置

比如在@app下加个lib目录,那再在这里加个Alipay类的话,类的命名空间和代码是这样的:

namespace app\lib;

class Alipay{}