3.2.2 - Laravel - 5.6 - Route - group属性合并
上一节中3.2.1中,我们讲到路由的group方法第一步中,涉及到了把group的属性attributes数据和groupStack数组中的最后一个数据合并:再来看下上一节说到的合并代码
public function mergeWithLastGroup($new)
{
return RouteGroup::merge($new, end($this->groupStack));
}
因为这个逻辑规则较多,单独拿出来分析一下。
再次明确一些定义:
1.RouteGroup是Route对象的集合,可以看成是一个路由表,一旦请求request过来就是去
RouteGroup的对象中寻找对应的route对象,进行对应的逻辑处理。这些route对象就是在上一节说到的group方法中注册的。
2.mergeWithLastGroup的参数$new
就是在编写定义group方法时,同时定义的group附带的namespace,prefix,middleware等属性attribute的集合。
接下来我们就进一步查看一下 RouteGroup的merge方法:
public static function merge($new, $old)
{
if (isset($new['domain'])) {
unset($old['domain']);
}
$new = array_merge(static::formatAs($new, $old), [
'namespace' => static::formatNamespace($new, $old),
'prefix' => static::formatPrefix($new, $old),
'where' => static::formatWhere($new, $old),
]);
return array_merge_recursive(Arr::except(
$old, ['namespace', 'prefix', 'where', 'as']
), $new);
}
分三步:
1.参数$new 就是group定义时候的新的属性,$old是groupStack数组中最后一个值,以前存进去的本来就有。
首先判断属性中是否存在domain这个属性。如果存在,$old数据中删除这个属性。但是后面会在最后一步把new中的domain属性合并。相当于重新更新了这个domain。
2.然后调用了四个方法分别比较新老数据中as, namespace, prefix, where
这四个属性,最后使用array_merge把他们合并成新的数组。
我们依次来看:
2.1 formatAs()
//别名的合并这里是前后拼接处理。
protected static function formatAs($new, $old)
{
if (isset($old['as'])) {
$new['as'] = $old['as'].($new['as'] ?? '');
}
return $new;
}
这个很简单,如果$old
中存在as字段的数据,就把as字段的数据和$new
中的as字段的数据前后拼接起来返回。
总结一下:这个例子中,如果嵌套了group,这个as就应该是
account.sub.
Route::group(['prefix'=>'accounts','as'=>'account.'], function(){ Route::group(['prefix'=>'accounts','as'=>'sub.'], function(){ Route::get('connect', 'AccountController@connect')->name('connect'); }); });
2.2 formatNamespace()
//namespace的合并通常就是字符串合并
protected static function formatNamespace($new, $old)
{
if (isset($new['namespace'])) {
return isset($old['namespace']) && strpos($new['namespace'], '\\') !== 0
? trim($old['namespace'], '\\').'\\'.trim($new['namespace'], '\\')
: trim($new['namespace'], '\\');
}
return $old['namespace'] ?? null;
}
1.如果$new
中没有namespace这个字段(就是group方法没有配置这个字段),就使用$old
的namespace数据返回。
2.否则,先判断,如果$old
中有namespace这个值,并且$new
中的namespace值不只是一个'\'
那就把$old
中的namespace和$new
中namesapce以 '\'
前后拼接起来。
2.3 formatPrefix
//前缀的合并也类似
protected static function formatPrefix($new, $old)
{
$old = $old['prefix'] ?? null;
return isset($new['prefix']) ? trim($old, '/').'/'.trim($new['prefix'], '/') : $old;
}
也很简单,
如果$new
中有配置prefix,就把他和$old
中的数据以'\'
间隔,拼接起来。如果没有直接使用$old
的prefix数据。
2.4 formatWhere
where属性用来对group中的路由路径,以正则表达式的方式进行配置时的设置。
protected static function formatWhere($new, $old)
{
return array_merge(
$old['where'] ?? [],
$new['where'] ?? []
);
}
这里是直接把这两个where规则合并为一个数组。变成规则组,很好理解,因为正则表达式不能用字符串合并嘛。
$old
的where可能针对的是所有group,或者准确的说是当前group的上一层group的正则表达式限制。new中的where针对的是当前group的正则表达式限制。
3.完成第二步所有的判断组合后,到了这一步
return array_merge_recursive(Arr::except(
$old, ['namespace', 'prefix', 'where', 'as']
), $new);
array_merge会对键名进行覆盖,而array_merge_recursive会把健名相同的合成为一个新数组。
这样就很好理解了。
这里首先调用了:Arr::except
用来清除$old
前面我们已经处理过的字段。然后再和$new
合并。(except
这个方法属于Arr类,这个类是对数组处理的工具类,有机会再讲。)
简单说就是,
$old
中没有处理过的字段也把他合并到$new
数组中。
总结下好了到这里,现在这个
$new
就是我们合并好了的数组,然后放在groupStack数组的尾部,对应了前一节3.2.1的内容了。
这就是整个group方法中属性合并的逻辑。基本解释了:如果当前group还有父group的属性attributes的情况下,group方法是如何拼接父group中的规则的。
最后强调下 group属性的这个合并机制是为了给后面加载路由对象使用的。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: