全部即時載入的服務註冊完成以後,會當即調用 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。