Yii2的深入学习--别名(Aliases)

王朝学院·作者佚名  2016-08-27  
宽屏版  字体: 小 | 中 | 大 | 超大  

在之前自动加载机制的文章中,我们有提到别名,提到 getAlias 方法,大家当时可能不太清楚,这到底是什么,今天我们就来说一下别名。

别名用来表示文件路径和 URL,这样就避免了将一些文件路径、URL以硬编码的方式写入代码中,或者多处出现一长串的文件路径、URL。

在 Yii2 中,一个别名必须以 @ 字符开头,Yii2 预定义了大量可用的别名,预定义的别名如下:

@yii 表示Yii框架所在的目录,也是 BaseYii.php 文件所在的位置@app 表示正在运行的应用的根目录@vendor 表示Composer 第三方库所在目录,一般是 @app/vendor 或 @app/../vendor@bower 表示 Bower 第三方库所在目录,一般是 @vendor/bower@npm 表示 NPM 第三方库所在目录,一般是 @vendor/npm@runtime 表示正在运行的应用的运行时用于存放运行时文件的目录,一般是 @app/runtime@webroot 表示正在运行的应用的入口文件 index.php 所在的目录,一般是 @app/web@web URL别名,表示当前应用的根URL,主要用于前端@common 表示通用文件夹@frontend 表示前台应用所在的文件夹@backend 表示后台应用所在的文件夹@console 表示命令行应用所在的文件夹其他使用Composer安装的Yii扩展注册的二级别名其中的 @common @frontend @backend 和 @console 在 baisc 的项目中是不会存在的。在 advanced 的项目中通常是定义在 common\config\bootstrap.php 文件中,其内容如下:

<?php

Yii::setAlias('common',dirname(__DIR__));

Yii::setAlias('frontend',dirname(dirname(__DIR__)) . '/frontend');

Yii::setAlias('backend',dirname(dirname(__DIR__)) . '/backend');

Yii::setAlias('console',dirname(dirname(__DIR__)) . '/console');

Yii2 中关于别名的设置和获取的方法都放在 BaseYii 类中,其结构基本如下:

<?phpclassBaseYii

{/**

* @var array registered path aliases

* @see getAlias()

* @see setAlias()

* Yii 的路径别名的 Map, 默认 @yii 指向当前目录*/publicstatic$aliases= ['@yii' =>__DIR__];/**

* Translates a path alias into an actual path.

* 将别名转化为真实的路径*/publicstaticfunctiongetAlias($alias,$throwException=true)

{...}/**

* Registers a path alias.

* 用一个真实的路径注册一个别名*/publicstaticfunctionsetAlias($alias,$path)

{...}

}

这是简化之后的 BaseYii 类的结构,其中有一个重要的变量 $aliases,两个重要的方法 getAlias 和 setAlias。$aliases 是存储 Yii2 路径别名的一个数组,key 是别名,value 是真实路径。getAlias 方法是根据别名获取到真实的地址,setAlias 是用一个真实的地址去注册一个别名。

先来看下 setAlias 方法,其内容如下:

/**

* Registers a path alias.

*

* 用一个真实的路径注册一个别名

*

* A path alias is a short name rePResenting a long path (a file path, a URL, etc.)

* For example, we use '@yii' as the alias of the path to the Yii framework directory.

*

* A path alias must start with the character '@' so that it can be easily differentiated

* from non-alias paths.

*

* Note that this method does not check if the given path exists or not. All it does is

* to associate the alias with the path.

*

* Any trailing '/' and '\' characters in the given path will be trimmed.

*

* @param string $alias the alias name (e.g. "@yii"). It must start with a '@' character.

* It may contain the forward slash '/' which serves as boundary character when performing

* alias translation by [[getAlias()]].

* @param string $path the path corresponding to the alias. If this is null, the alias will

* be removed. Trailing '/' and '\' characters will be trimmed. This can be

*

* - a directory or a file path (e.g. `/tmp`, `/tmp/main.txt`)

* - a URL (e.g. `http://www.yiiframework.com`)

* - a path alias (e.g. `@yii/base`). In this case, the path alias will be converted into the

* actual path first by calling [[getAlias()]].

*

* @throws InvalidParamException if $path is an invalid alias.

* @see getAlias()*/publicstaticfunctionsetAlias($alias,$path)

{if(strncmp($alias, '@', 1)) {//如果不是以 @ 开头,就将 @ 拼到开头$alias= '@' .$alias;

}//获取 / 在 $alias 中首次出现的位置$pos=strpos($alias, '/');//如果 / 不存在,$root 就是整个 $alias,否则就是 $alias 中 / 前的内容$root=$pos===false?$alias:substr($alias, 0,$pos);if($path!==null) {//如果 $path 以 @ 开头,使用 getAlias 去获取路径,否则,就去除掉最右边的 /$path=strncmp($path, '@', 1) ?rtrim($path, '\\/') :static::getAlias($path);if(!isset(static::$aliases[$root])) {//如果不存在这个 $root 的别名if($pos===false) {//没有 /,就将 $path 直接赋值以为 $root 别名对应的路径static::$aliases[$root] =$path;

}else{//否则,就将 $path 直接赋值为 $root 下的 $alias 的路径static::$aliases[$root] = [$alias=>$path];

}

}elseif(is_string(static::$aliases[$root])) {//如果存在,而且是个string类型if($pos===false) {//没有 /,意味着 $alias 就是 $root,直接覆盖即可static::$aliases[$root] =$path;

}else{//否则,就合并到一起static::$aliases[$root] =[$alias=>$path,$root=>static::$aliases[$root],];

}

}else{//这种,正常是个 array 类型

// 直接添加进去即可static::$aliases[$root][$alias] =$path;//krsort — 对数组按照键名逆向排序

// 可以做到优先匹配长的别名krsort(static::$aliases[$root]);

}

}elseif(isset(static::$aliases[$root])) {//$path 为空且对应的别名有值存在,就是要移除相应的别名if(is_array(static::$aliases[$root])) {//如果 $root 的别名对应一个 array,就只移除掉对应的别名即可unset(static::$aliases[$root][$alias]);

}elseif($pos===false) {//如果 $root 的别名对应不是一个 array 而且 $root 就是 $alias,就移除这个 $root 的别名unset(static::$aliases[$root]);

}

}

}

下面举几个例子来说明,别名写入后,$aliases 中的内容变化。

//初始 BaseYii::aliases['@foo'] = 'path/to/foo'Yii::setAlias('@foo', 'path/to/foo');//直接覆盖 BaseYii::aliases['@foo'] = 'path/to/foo2'Yii::setAlias('@foo', 'path/to/foo2');/**

* 新增

* BaseYii::aliases['@foo'] = [

* '@foo/bar' => 'path/to/foo/bar',

* '@foo' => 'path/to/foo2',

* ];*/Yii::setAlias('@foo/bar', 'path/to/foo/bar');//初始 BaseYii::aliases['@bar'] = ['@bar/qux' => 'path/to/bar/qux'];Yii::setAlias('@bar/qux', 'path/to/bar/qux');//直接覆盖 BaseYii::aliases['@bar'] = ['@bar/qux' => 'path/to/bar/qux2'];Yii::setAlias('@bar/qux', 'path/to/bar/qux2');/**

* 新增

* BaseYii::aliases['@bar'] = [

* '@bar/foo' => 'path/to/bar/foo',

* '@bar/qux' => 'path/to/bar/qux2',

* ];*/Yii::setAlias('@bar/foo', 'path/to/bar/foo');/**

* 新增

* BaseYii::aliases['@bar'] = [

* '@bar/foo' => 'path/to/bar/foo',

* '@bar/qux' => 'path/to/bar/qux2',

* '@bar' => 'path/to/bar',

* ];*/Yii::setAlias('@bar', 'path/to/bar');/**

* 删除

* BaseYii::aliases['@bar'] = [

* '@bar/foo' => 'path/to/bar/foo',

* '@bar' => 'path/to/bar',

* ];*/Yii::setAlias('@bar/qux',null);/**

* 删除

* BaseYii::aliases['@bar'] = [

* '@bar/foo' => 'path/to/bar/foo',

* ];*/Yii::setAlias('@bar',null);

再来看一下 getAlias 方法,其内容如下:

/**

* Translates a path alias into an actual path.

* 将别名转化为真实的路径

*

* The translation is done according to the following procedure:

*

* 1. If the given alias does not start with '@', it is returned back without change;

* 2. Otherwise, look for the longest registered alias that matches the beginning part

* of the given alias. If it exists, replace the matching part of the given alias with

* the corresponding registered path.

* 3. Throw an exception or return false, depending on the `$throwException` parameter.

*

* For example, by default '@yii' is registered as the alias to the Yii framework directory,

* say '/path/to/yii'. The alias '@yii/web' would then be translated into '/path/to/yii/web'.

*

* If you have registered two aliases '@foo' and '@foo/bar'. Then translating '@foo/bar/config'

* would replace the part '@foo/bar' (instead of '@foo') with the corresponding registered path.

* This is because the longest alias takes precedence.

*

* However, if the alias to be translated is '@foo/barbar/config', then '@foo' will be replaced

* instead of '@foo/bar', because '/' serves as the boundary character.

*

* Note, this method does not check if the returned path exists or not.

*

* @param string $alias the alias to be translated.

* @param boolean $throwException whether to throw an exception if the given alias is invalid.

* If this is false and an invalid alias is given, false will be returned by this method.

* @return string|boolean the path corresponding to the alias, false if the root alias is not previously registered.

* @throws InvalidParamException if the alias is invalid while $throwException is true.

* @see setAlias()*/publicstaticfunctiongetAlias($alias,$throwException=true)

{/**

* strncmp — 二进制安全比较字符串开头的若干个字符

* int strncmp ( string $str1 , string $str2 , int $len )

* 如果 $alias 不是以 '@' 开头的,就不是一个 Yii 的别名*/if(strncmp($alias, '@', 1)) {//not an aliasreturn$alias;

}//获取 / 在 $alias 中首次出现的位置$pos=strpos($alias, '/');//如果 / 不存在,$root 就是整个 $alias,否则就是 $alias 中 / 前的内容$root=$pos===false?$alias:substr($alias, 0,$pos);//如果存在 $root 的别名if(isset(static::$aliases[$root])) {if(is_string(static::$aliases[$root])) {//如果 $root 对应的别名是一个字符串,之直接返回 $aliases[$root] 或者 $aliases[$root] . substr($alias, $pos)

// 当 $root 就是 $alias 返回 $aliases[$root], 否则就在拼接上 $alias 除去 $root 后,剩下的字符串return$pos===false?static::$aliases[$root] :static::$aliases[$root] .substr($alias,$pos);

}else{//否则,要遍历整个 $aliases[$root] 数组,找到 $name 与 $alias 相同的值,返回 $path . substr($alias, strlen($name))

// 其实是返回了 $path 拼接上 $alias 除去 $root 后,剩下的字符串foreach(static::$aliases[$root]as$name=>$path) {if(strpos($alias. '/',$name. '/') === 0) {return$path.substr($alias,strlen($name));

}

}

}

}if($throwException) {thrownewInvalidParamException("Invalid path alias:$alias");

}else{returnfalse;

}

}

好了,关于别名就先说这么多~~

对 Yii2源码有兴趣的同学可以关注项目 yii2-2.0.3-annotated,现在在上面已经添加了不少关于 Yii2 源码的注释,之后还会继续添加~

有兴趣的同学也可以参与进来,提交 Yii2 源码的注释。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有