这一章我们继续寻找它们。
老规矩先来一个目录
setAlias函数
getAlias函数
setAlias函数
通过对上一篇的学习,我们知道在一个yii application对象生成的过程中就已经通过setAlias方法对预定义的别名进行了初始化工作,在以后的程序代码中,可以随时使用它们,那么setAlias到底将这些别名放到了哪里那?
我们现在来揭开setAlias的面纱,根据Yii2的约定,setAlias被设计在YiiBase.php
//路径 vendor/yiisoft/yii2/BaseYii.php
public static function setAlias($alias, $path)
{
if (strncmp($alias, '@', 1)) {
$alias = '@' . $alias;
}
$pos = strpos($alias, '/');
$root = $pos === false ? $alias : substr($alias, 0, $pos);
if ($path !== null) {
$path = strncmp($path, '@', 1) ? rtrim($path, '\\/') : static::getAlias($path);
if (!isset(static::$aliases[$root])) {
if ($pos === false) {
static::$aliases[$root] = $path;
} else {
static::$aliases[$root] = [$alias => $path];
}
} elseif (is_string(static::$aliases[$root])) {
if ($pos === false) {
static::$aliases[$root] = $path;
} else {
static::$aliases[$root] = [
$alias => $path,
$root => static::$aliases[$root],
];
}
} else {
static::$aliases[$root][$alias] = $path;
krsort(static::$aliases[$root]);
}
} elseif (isset(static::$aliases[$root])) {
if (is_array(static::$aliases[$root])) {
unset(static::$aliases[$root][$alias]);
} elseif ($pos === false) {
unset(static::$aliases[$root]);
}
}
}
现在通过对setAlias的分析来教大家如何设置一个别名。
if (strncmp($alias, '@', 1)) {
$alias = '@' . $alias;
}
看完上面代码后你应该知道我们设置一个别名的时候Yii::setAlias($name,$val),$name可以不以@开头,Yii会自动去添加,当然如果你填了也没关系。
比如下面两个别名的设置是一个意思。
Yii::setAlias('@abei','/web/static');
Yii::setAlias('abei','/web/static');
另外setAlias会将所有有效的别名存到YiiBase的$aliases变量中,并且它会将具有相同规范的别名放到一个别名数组中,这一点要注意,而setAlias的大部分逻辑也是在分析这个别名数组,它首先通过"/"标记符来分析别名名称,具体代码
$root = $pos === false ? $alias : substr($alias, 0, $pos);
例如我们设置如下的别名
Yii::setAlias('@abei','/web');
Yii::setAlias('@abei/father','/web/father');
Yii会这样存储它们:
还有我们如果设置了如下别名
Yii::setAlias('@abei/child','/web/child');
Yii::setAlias('@abei/father','/web/father');
Yii会这样存储它们:
要注意:虽然setAlias通过"/"标记符来规划别名数组,但是只是受限于第一层,例如我们写了如下另个别名
Yii::setAlias('@abei/world/child','/web/child');
Yii::setAlias('@abei/world/father','/web/father');
并不会存为二维数组,而依然是一维数组。
到此刻你应该明白了具有相同前缀的别名在yii中的存在形式,还有一个很需要注意的事情,就是你如何注销一个已经定义的别名,我说的不是变为空,而是彻底的注销。
你只要按照下面的代码就可以
Yii::setAlias('@webroot',null);
是的,设置为空,则@webroot将从别名数组中将消失、是消失、是消失。
此刻你在运行
$a = Yii::getAlias('@webroot');
echo $a;
一个报错出现了,它验证了我说明的:
到此为止,北哥给你说了setAlias的一个实现思路,我们总结一下
别名存放到了YiiBase的$aliases变量中
当自定义的别名被/分隔的时候,Yii会以数组形式将其存放到$aliases变量中
如果我们想注销一个已经存在的别名,需将其设置为null
我建议大家带着对setAlias的理解再学习下上一篇,别名的初始化,你会有更深刻的理解。
getAlias 函数
上面我们学习了将一个别名进行set,现在我们在说下Yii2是如何读取一个别名的那?
getAlias仍然在YiiBase.php文件中,代码如下:
//路径 vendor/yiisoft/yii2/BaseYii.php
public static function getAlias($alias, $throwException = true)
{
if (strncmp($alias, '@', 1)) {
// not an alias
return $alias;
}
$pos = strpos($alias, '/');
$root = $pos === false ? $alias : substr($alias, 0, $pos);
if (isset(static::$aliases[$root])) {
if (is_string(static::$aliases[$root])) {
return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos);
}
foreach (static::$aliases[$root] as $name => $path) {
if (strpos($alias . '/', $name . '/') === 0) {
return $path . substr($alias, strlen($name));
}
}
}
if ($throwException) {
throw new InvalidParamException("Invalid path alias: $alias");
}
return false;
}
当我们对setAlias函数了解后,对于getAlias变得再简单不过了,它只不过是对字符串类型的别名(如@wwwroot)和数组型别名(如@abei/world/child)的解析罢了。
我们先通过下图对getAlias有一个整体的了解
通过上面代码知道,你在使用getAlias的时候一定要记住一点的是传递给getAlias应是一个别名或包含别名开头的路径。
例如下面的格式都是合法的
//@webroot和@abei/world/child被预先定义
Yii::getAlias('@webroot');
Yii::getAlias('@webroot/abc');
Yii::getAlias('@abei/world/child');
但是你不能写
//@webroot被预先定义
Yii::getAlias('abc@webroot');//不进行解析,直接返回abc@webroot
Yii::getAlias('@webrootabc');//报错,提示不存在改别名
最后要注意一点的就是,对于数组类型的别名,yii2会遍历整个数组,然后依次进行匹配,知道匹配到第一个和传递的参数吻合的后返回。
例如我们定义了2个别名
Yii::setAlias('@abei/world/child','/web/child');
Yii::setAlias('@abei/world/father','/web/father');
然后我们在代码里使用的别名如下
Yii::getAlias('@abei/world/father/abc');
则Yii2进行了如下图的操作
要记住的一点:匹配的是@xxxx/,末尾有个反斜杠哦。具体为何请自行思考,结合setAlias思考。
以上就是别名的定义和读取原则,当你读完后是否发现别名其实很easy,别想的太复杂~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。