要先说一句,不要尝试修改yii预定义的别名,除非你的脑袋被驴踢了
由于开发需要,我们有时需要将一些路径或url保存起来,避免直接写入代码中,于是我们一定了一个类似于常量的变量,在全局均可以使用,这个变量就叫别名,当然你也可以在配置文件中
进行设置。
在yii中我们可以人为指定别名并使用它们,并且、yii框架还默认提供了12个预定义的别名,即使你没看懂本文,记住这12个别名,也能极大的提高编码质量。
预定义的别名
- @yii表示yii框架所在目录,也就是yii\BaseYii类文件所在的位置(vendor/yiisoft/yii2/BaseYii.php)
- @app 表示应用运行的根目录、非web目录;
- @vendor 表示composer第三方库安装目录,你通过composer安装,包括yiisoft核心库都在这里;
- @bower 表示bower第三方库安装目录,一般在vendor/bower里(该库主要存放一些例如jquery的库文件);
- @npm 表示npm第三方库安装目录,一般为vendor/npm;
- @runtime 表示正在运行的应用的运行时用于存放运行时文件的目录,比如缓存、日志等等
- @webroot 表示正在运行的应用的入口文件index.php文件所在的目录,一般是指@app/web,记住这里指的是物理路径;
- @web 表示当前运行的Web应用程序的 base URL。它的值与 yii\web\Request::$baseUrl 相同,主要用于前端(末尾不带/)
一下4个只会在yii高级版本中看到,基础版请飞过
- @common 表示通用文件夹
- @frontend 表示前台应用所在的文件夹
- @backend 表示后台应用所在的文件夹
- @console 表示命令行应用所在文件夹
对于这12个预定义别名,重点关注的是@web,它是唯一一个url类型的,其他均为服务器物理路径,@web代表应用的url,且后面不带/斜杠。
为何全局能用
是的,如果想全局使用,那就要在入口或yii这个应用建立之时就开始定义它们,只有这才可以。
那我就一步一步开始吧,首先我们访问入口文件,入口文件做了两件事
- 加载应用配置文件
- 将配置文件传递给application,生成一个 yii application
当程序执行了
(new yii\web\Application($config))->run();
我们解释就是$config传递给Application类,并且生成一个应用对象,这个新建过程由Application的构造函数完成。
而你也发现Application本身并没有构造函数,那么他使用的是其父类\yii\base\Application 的构造函数
public function __construct($config = [])
{
Yii::$app = $this;
static::setInstance($this);
$this->state = self::STATE_BEGIN;
$this->preInit($config);
$this->registerErrorHandler($config);
Component::__construct($config);
}
preInit 关键就在于preInit这个函数,它完成了类似@vendor、@runtime等预定义别名的定义工作,例如@vendor
public function setVendorPath($path)
{
$this->_vendorPath = Yii::getAlias($path);
Yii::setAlias('@vendor', $this->_vendorPath);
Yii::setAlias('@bower', $this->_vendorPath . DIRECTORY_SEPARATOR . 'bower');
Yii::setAlias('@npm', $this->_vendorPath . DIRECTORY_SEPARATOR . 'npm');
}
因为这些操作都是在入口文件实例化Application类的时候建立,因此在之后的所有操作中都可以直接使用预定义别名。
到此时你可能明白为何可以全局使用了吧。
非也,你会发现@web和@webroot并没有一个函数去定义它们!没错,因为\yii\base\Application 是yii抽象出来的基本Application类,实际运行中会有类似yii\web\Application、yii\console\Application进行继承然后实例化为各种场景的Application。
说到这里你不难理解没有@web和@webroot的预定义了吧,\yii\base\Application仅仅负责yii最基本的预定义别名的定义,而@web和@webroot属于web的东东,应该由子类yii\web\Application来定义,那么我们开始寻找它。
眼神1.5的你一定在 yii\web\Application 中发现了下面的代码
protected function bootstrap()
{
$request = $this->getRequest();
Yii::setAlias('@webroot', dirname($request->getScriptFile()));
Yii::setAlias('@web', $request->getBaseUrl());
parent::bootstrap();
}
是滴,我们的确找到了答案,现在所有的预定于别名都找到了出处,至于当我们建立Application对象的时候是如何调用bootstrap函数的,这里不进行说明,请你按类的继承关系进行分析,就知道咋回事了