路由的group方法中涉及到了把group的屬性attributes以特定的規則和groupStack陣列中的最後一個資料合併:
public function mergeWithLastGroup($new)
{
return RouteGroup::merge($new, end($this->groupStack));
}
因為邏輯規則較多,單獨拿出來分析。
先明確一些定義:
1.RouteGroup是Route物件的集合,可以看成是一個路由表,一旦請求request過來就是去
RouteGroup的物件中尋找對應的route物件,進行對應的邏輯處理。
2.mergeWithLastGroup的引數$new
就是定義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屬性合併。
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欄位的資料前後拼接起來返回。
2.2 formatNamespace()
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
陣列中。
這就是整個合併的邏輯。基本解釋拼接或者是替換。
本作品採用《CC 協議》,轉載必須註明作者和本文連結