全部即时载入的服务注册完成以后,会当即调用 register 方法,并标记为已载入。 随后经过 \Illuminate\Foundation\Bootstrap\BootProviders 启动项来调用全部的即时加载服务提供者的 boot 方法 查看根据 config/app.php 中的 providers 生成的 bootstrap/cache/services.php 'eager' => array ( // 系统服务提供者 0 => 'Illuminate\\Auth\\AuthServiceProvider', // 注入验证相关对象 1 => 'Illuminate\\Cookie\\CookieServiceProvider', // 注入cookie对象 2 => 'Illuminate\\Database\\DatabaseServiceProvider', // 注入db相关对象 3 => 'Illuminate\\Encryption\\EncryptionServiceProvider', // 注入加解密对象 4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider', // 注入文件相关对象 5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider',// 注入基础的请求对象 6 => 'Illuminate\\Notifications\\NotificationServiceProvider', // 注入通知对象 7 => 'Illuminate\\Pagination\\PaginationServiceProvider', // 注入分页相关对象 8 => 'Illuminate\\Session\\SessionServiceProvider', // 注入session相关对象 9 => 'Illuminate\\View\\ViewServiceProvider', // 注入视图相关对象 10 => 'Laravel\\Passport\\PassportServiceProvider', // 注入passport相关对象 // 配置项服务提供者 11 => 'App\\Providers\\AppServiceProvider', 12 => 'App\\Providers\\AuthServiceProvider', 13 => 'App\\Providers\\EventServiceProvider', 14 => 'App\\Providers\\RouteServiceProvider', )
// 主要是注册完以后的 boot 方法调用 App\\Providers\\RouteServiceProvider public function boot() { // 能够加入本身的操做 parent::boot(); } public function boot() { $this->setRootControllerNamespace(); // 若执行了 php artisan routes:cache(自动生成路由缓存文件,注意:建议只在项目上线时操做),直接加载 if ($this->app->routesAreCached()) { $this->loadCachedRoutes(); } else { // 加载路由 $this->loadRoutes(); // 设置系统启动时的事件监听函数 $this->app->booted(function () { $this->app['router']->getRoutes()->refreshNameLookups(); }); } } protected function setRootControllerNamespace() { if (! is_null($this->namespace)) { // 设置 $this->instances['url'] (\Illuminate\Routing\UrlGenerator对象)的 rootNamespace 属性 $this->app[UrlGenerator::class]->setRootControllerNamespace($this->namespace); } } public function routesAreCached() { return $this['files']->exists($this->getCachedRoutesPath()); } public function getCachedRoutesPath() { return $this->bootstrapPath().'/cache/routes.php'; } protected function loadRoutes() { if (method_exists($this, 'map')) { $this->app->call([$this, 'map']); } } public function map() { $this->mapApiRoutes(); $this->mapWebRoutes(); } // API 相关的路由 protected function mapApiRoutes() { Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); } // WEB 相关的路由 protected function mapWebRoutes() { Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); } public function booted($callback) { $this->bootedCallbacks[] = $callback; // 若是应用已经启动了,则直接调用 if ($this->isBooted()) { $this->fireAppCallbacks([$callback]); } } // Route 是 Facde 的调用方式 分析: Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); Route::middleware public static function __callStatic($method, $args) { // 获取应用的 router 对象 $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } // 将 Router::middleware() 转化为应用的 Router->middleware() 方式,若 Router 没有 middleware 方法,则直接触发 __call return $instance->$method(...$args); } public function __call($method, $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } // 将不存在的方法的调用委托给 RouteRegistrar 处理, return (new RouteRegistrar($this))->attribute($method, $parameters[0]); } public function attribute($key, $value) { // 只容许指定的属性设置($allowedAttributes = ['as', 'domain', 'middleware', 'name', 'namespace', 'prefix',]) if (! in_array($key, $this->allowedAttributes)) { throw new InvalidArgumentException("Attribute [{$key}] does not exist."); } // 支持.方式来存放属性 $this->attributes[array_get($this->aliases, $key, $key)] = $value; return $this; } public function group($callback) { $this->router->group($this->attributes, $callback); } public function group(array $attributes, $routes) { $this->updateGroupStack($attributes); $this->loadRoutes($routes); array_pop($this->groupStack); } protected function loadRoutes($routes) { if ($routes instanceof Closure) { $routes($this); } else { $router = $this; require $routes; } }
小结php
Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); 实际就是将 middleware namespace 加入到 RouteRegistrar 对象里面的 attributes 数组属性,并返回 RouteRegistrar 对象,再调用 RouteRegistrar 对象的 group 方法,也就是调用 router 对象的 group 方法。最终就是将['middleware' => 'web', 'namespace' => $this->namespace] 数组设置给 $this->router 的groupStack 属性(将运用到全部的路由),再加载 config/web.php。