3.2 - Laravel - 5.6 - Route - group屬性合併

HarveyNorman發表於2020-09-20

路由的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 協議》,轉載必須註明作者和本文連結

相關文章