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 协议》,转载必须注明作者和本文链接
推荐文章: