3.2.1 - Laravel - 5.6 - Route - 路由配置文件加载 之 Group方法解析

group方法在路由中起到对固定一批路由统一规则的作用。
简单说就是一个group方法下的路由都可以设置相同的路由规则。参考文档的使用一下就明白了。

最最重要的是这个group方法也是加载路由配置文件web.php的主要方法,laravel本身把整个路由配置文件视为一个路由的group操作。

直接看group的源代码:

public function group(array $attributes, $routes)
{
    $this->updateGroupStack($attributes);
    $this->loadRoutes($routes);
    array_pop($this->groupStack);
}

这里逻辑主要是三步:

1.首先使用updateGroupStack方法更新groupStack数组。
$this->updateGroupStack($attributes);

groupStack数组用来存储所有group的attributes数据。
比如:
middleware – group下面路由的中间件
namespace – group对应路由action的命名空间
prefix – group对应路由url的前缀

updateGroupStack源码如下:

protected function updateGroupStack(array $attributes)
{
    if (! empty($this->groupStack)) {
        $attributes = $this->mergeWithLastGroup($attributes);
    }

    $this->groupStack[] = $attributes;
}

很简单,如果groupStack这个数组不为空,(说明上面还有一些group的全局规则)。那么就使用mergeWithLastGroup方法merge当前的attributes(attribute就是当前group的规则)到groupStack数组的最后一个数据中。
然后把当前这个group的attributes加到groupStack栈的尾部。这里强调一下尾部因为栈的结构后进先出,最靠近当前group的attributes数据放在最后。

1.1 然后看下mergeWithLastGroup方法。

public function mergeWithLastGroup($new)
{
    return RouteGroup::merge($new, end($this->groupStack));
}

a.end($this->groupStack) :end()方法获取groupStack最后一个数据。
b.调用RouteGroup的merge方法组合attributes和group中的最后一个数据。

这里的merge方法细节较多。具体细节放在了下一节 3.2 - Laravel - 5.6 - Route - 路由group合并。


2.回到group方法,第二步$this->loadRoutes($routes); 加载路由
完成更新groupstack后,使用loadRoutes方法加载路由。代码如下:

protected function loadRoutes($routes)
    {
        if ($routes instanceof Closure) {
            $routes($this);
        } else {
            (new RouteFileRegistrar($this))->register($routes);
        }
    }

a.如果这个$routes是一个闭包函数,就直接执行。
b.否则创建一个RouteFileRegistrar对象来调用register方法注册这个$routes

2.1 我们看下RouteFileRegistrar的register方法。

public function register($routes)
    {
        $router = $this->router;
        require $routes;
    }

很明了,就是使用require引入$routes

这说明$routes可以是一个路径。require可以直接加载整个文件或者文件路径。


** 第二步总结:**
1.到这里就很明确了。这一步$this->loadRoutes($routes); 简单说就是:如果group方法提供的参数是闭包函数,比如下面这种。(第二个参数是function闭包。)

Route::group(['middleware' => ['auth', 'verified']], function() {
    Route::get('user_addresses', 'UserAddressesController@index');
....

,这里就会执行这个路由的闭包函数。也就是加载这个路由。执行的是Route::get()方法。(get方法这里仅仅是对这个路由的注册)

2.否则则会判定这是一个文件路径,会使用require引入这个文件。然后依次执行文件中的方法。
这种文件路径的具体的使用的例子在 加载路由配置文件web.php,api.php的时候会使用到。
例子如下:路由前期初始化的时候加载配置文件调用的group方法如下:

protected function mapWebRoutes()
{
    Route::middleware('web')
            ->namespace($this->namespace)
            ->group(base_path('routes/web.php'));
}

这里就是通过require加载了routes/web.php这个文件。

加载配置文件的具体流程会在章节: 加载RouteServiceProvider中涉及。这里不再累述。

3.最后group()方法的第三步:完成路由的加载后,需要从groupStack中去除刚刚已经添加的路由的属性规则(attribute)。

array_pop($this->groupStack);

为的是不让当前路由的attribute不影响其他路由。
在第一步添加的路由属性attributes数据要在这里(第三步)删除,保证当前加载的路由group属性attributes不针对其他路由。

这个说明在注册路由对象的时候(就是执行 Route::get(), Route::post方法的时候),并没有执行清理,而是在这里进行了当前路由属性attributes的清理。


总结:

路由的group方法在类Router中提供。group方法提供了两种方式来进行路由的加载,一个是闭包,一个是路径的方式。
group对应的参数attributes以栈的形式存储。可以形成一个嵌套,如果存在多个层级的group的话。
最后强调下,group方法是对路由的加载,把一个一个路由代码创建成一个一个对象,然后等待着请求request来调用。

举例 :web.php下面的这段代码将会被group方法加载web.php执行后,变成一个route对象存储其起来,等待请求的到来。

Route::get('connect', 'AccountController@connect')->name('connect');
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!