本篇文章給大家?guī)砹岁P(guān)于laravel的相關(guān)知識,其中主要介紹了關(guān)于laravel的生命周期相關(guān)問題,laravel 的生命周期從publicindex.php開始,從publicindex.php結(jié)束,希望對大家有幫助。
【相關(guān)推薦:laravel】
Laravel的生命周期 A
世間萬物皆有生命周期,當(dāng)我們使用任何工具時都需要理解它的工作原理,那么用起來就會得心應(yīng)手,應(yīng)用開發(fā)也是如此。理解了它的原理,那么使用起來就會游刃有余。
在了解 Laravel 的生命周期前,我們先回顧一下PHP 的生命周期。
PHP 的運行模式
PHP兩種運行模式是WEB模式、CLI模式。
當(dāng)我們在終端敲入php這個命令的時候,使用的是CLI模式。
當(dāng)使用nginx或者別web服務(wù)器作為宿主處理一個到來的請求時,使用的是WEB模式。
PHP 的生命周期
當(dāng)我們請求一個php文件時,PHP 為了完成這次請求,會發(fā)生5個階段的生命周期切換:
-
1 模塊初始化(MINIT),即調(diào)用 php.ini 中指明的擴展的初始化函數(shù)進行初始化工作,如 mysql 擴展。
-
2 請求初始化(RINIT),即初始化為執(zhí)行本次腳本所需要的變量名稱和變量值內(nèi)容的符號表,如 $_SESSION變量。
-
3 執(zhí)行該PHP腳本。
-
4 請求處理完成(Request Shutdown),按順序調(diào)用各個模塊的 RSHUTDOWN 方法,對每個變量調(diào)用 unset 函數(shù),如 unset $_SESSION 變量。
-
5 關(guān)閉模塊(Module Shutdown) , PHP調(diào)用每個擴展的 MSHUTDOWN 方法,這是各個模塊最后一次釋放內(nèi)存的機會。這意味著沒有下一個請求了。
WEB模式和CLI(命令行)模式很相似,區(qū)別是:
CLI 模式會在每次腳本執(zhí)行經(jīng)歷完整的5個周期,因為你腳本執(zhí)行完不會有下一個請求;
WEB模式為了應(yīng)對并發(fā),可能采用多線程,因此生命周期1和5有可能只執(zhí)行一次,下次請求到來時重復(fù)2-4的生命周期,這樣就節(jié)省了系統(tǒng)模塊初始化所帶來的開銷。
可以看出PHP生命周期是很對稱的。說了這么多,就是為了定位Laravel運行在哪里,沒錯,Laravel僅僅運行再 第三個階段:
作用
理解這些,你就可以優(yōu)化你的 Laravel 代碼,可以更加深入的了解 Laravel 的singleton(單例)。
至少你知道了,每一次請求結(jié)束,PHP 的變量都會 unset,Laravel 的 singleton 只是在某一次請求過程中的singleton;
你在 Laravel 中的靜態(tài)變量也不能在多個請求之間共享,因為每一次請求結(jié)束都會 unset。
理解這些概念,是寫高質(zhì)量代碼的第一步,也是最關(guān)鍵的一步。因此記住,PHP是一種腳本語言,所有的變量只會在這一次請求中生效,下次請求之時已被重置,而不像Java靜態(tài)變量擁有全局作用。
Laravel 的生命周期
概述
Laravel 的生命周期從publicindex.php開始,從publicindex.php結(jié)束。
請求過程
下面是 publicindex.php的全部源碼,更具體來說可以分為四步:
<?php define('LARAVEL_START', microtime(true)); require __DIR__.'/../vendor/autoload.php'; $app = require_once __DIR__.'/../bootstrap/app.php'; $kernel = $app->make(IlluminateContractshttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); $response->send(); $kernel->terminate($request, $response);
以下是四步詳細的解釋是:composer自動加載需要的類
- 1 文件載入composer生成的自動加載設(shè)置,包括所有你 composer require的依賴。
- 2 生成容器 Container,Application實例,并向容器注冊核心組件(HttpKernel,consoleKernel ,ExceptionHandler)(對應(yīng)代碼2,容器很重要,后面詳細講解)。
- 3 處理請求,生成并發(fā)送響應(yīng)(對應(yīng)代碼3,毫不夸張的說,你99%的代碼都運行在這個小小的handle 方法里面)。
- 4 請求結(jié)束,進行回調(diào)(對應(yīng)代碼4,還記得可終止中間件嗎?沒錯,就是在這里回調(diào)的)。
Laravel 的請求步驟
第一步:注冊加載composer自動生成的class loader
就是加載初始化第三方依賴。
第二步:生成容器 Container
并向容器注冊核心組件,是從 bootstrap/app.php 腳本獲取 Laravel 應(yīng)用實例,
第三步:這一步是重點,處理請求,并生成發(fā)送響應(yīng)。
請求被發(fā)送到 HTTP 內(nèi)核或 Console 內(nèi)核,這取決于進入應(yīng)用的請求類型。
取決于是通過瀏覽器請求還是通過控制臺請求。這里我們主要是通過瀏覽器請求。
HTTP 內(nèi)核繼承自 IlluminateFoundationHttpKernel 類,該類定義了一個 bootstrappers 數(shù)組,這個數(shù)組中的類在請求被執(zhí)行前運行,這些 bootstrappers 配置了錯誤處理、日志、檢測應(yīng)用環(huán)境以及其它在請求被處理前需要執(zhí)行的任務(wù)。
protected $bootstrappers = [ //注冊系統(tǒng)環(huán)境配置 (.env) 'IlluminateFoundationBootstrapDetectEnvironment', //注冊系統(tǒng)配置(config) 'IlluminateFoundationBootstrapLoadConfiguration', //注冊日志配置 'IlluminateFoundationBootstrapConfigureLogging', //注冊異常處理 'IlluminateFoundationBootstrapHandleExceptions', //注冊服務(wù)容器的門面,F(xiàn)acade 是個提供從容器訪問對象的類。 'IlluminateFoundationBootstrapregisterFacades', //注冊服務(wù)提供者 'IlluminateFoundationBootstrapRegisterProviders', //注冊服務(wù)提供者 `boot` 'IlluminateFoundationBootstrapBootProviders', ];
Laravel的生命周期 B
laravel/public/index.php
/** * laravel的啟動時間 */ define('LARAVEL_START', microtime(true)); /** * 加載項目依賴。 * 現(xiàn)代PHP依賴于Composer包管理器,入口文件通過引入由Composer包管理器。 * 自動生成的類加載程序,可以輕松注冊并加載所依賴的第三方組件庫。 */ require __DIR__.'/../vendor/autoload.php'; /** * 創(chuàng)建laravel應(yīng)用實例。 */ $app = require_once __DIR__.'/../bootstrap/app.php'; // 接受請求并響應(yīng) $kernel = $app->make(IlluminateContractsHttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); // 結(jié)束請求,進行回調(diào) $response->send(); // 終止程序 $kernel->terminate($request, $response);
laravel/boostrap/app.php
# 第一部分:創(chuàng)建應(yīng)用實例 $app = new IlluminateFoundationApplication( realpath(__DIR__.'/../') ); # 第二部分:完成內(nèi)核綁定 $app->singleton( IlluminateContractsHttpKernel::class, AppHttpKernel::class ); $app->singleton( IlluminateContractsConsoleKernel::class, AppConsoleKernel::class ); $app->singleton( IlluminateContractsDebugExceptionHandler::class, AppExceptionsHandler::class ); return $app;
laravelvendorlaravelframeworksrcIlluminateFoundationHttpKernel.php
class Kernel implements KernelContract { protected $bootstrappers = [ IlluminateFoundationBootstrapLoadEnvironmentVariables::class, // 注冊系統(tǒng)環(huán)境配置 IlluminateFoundationBootstrapLoadConfiguration::class, // 注冊系統(tǒng)配置 IlluminateFoundationBootstrapHandleExceptions::class, // 注冊異常注冊 IlluminateFoundationBootstrapRegisterFacades::class, // 注冊門面模式 IlluminateFoundationBootstrapRegisterProviders::class, // 注冊服務(wù)提供者 IlluminateFoundationBootstrapBootProviders::class, // 注冊服務(wù)提供者boot ]; // 處理請求 public function handle($request) { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new EventsRequestHandled($request, $response) ); return $response; } protected function sendRequestThroughRouter($request) { # 一、將$request實例注冊到APP容器 $this->app->instance('request', $request); # 二、清除之前的$request實例緩存 Facade::clearResolvedInstance('request'); # 三、啟動引導(dǎo)程序 $this->bootstrap(); # 四、發(fā)送請求 return (new Pipeline($this->app)) //創(chuàng)建管道 ->send($request) //發(fā)送請求 ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) //通過中間件 ->then($this->dispatchToRouter()); //分發(fā)到路由 } # 啟動引導(dǎo)程序 public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } } # 路由分發(fā) protected function dispatchToRouter() { return function ($request) { $this->app->instance('request', $request); return $this->router->dispatch($request); }; } # 終止程序 public function terminate($request, $response) { $this->terminateMiddleware($request, $response); $this->app->terminate(); }
Laravel 服務(wù)容器模塊
簡介
服務(wù)容器是一個用于管理類依賴和執(zhí)行依賴注入的強大工具。是整個框架的核心;
幾乎所有的服務(wù)容器綁定都是在服務(wù)提供者中完成。
框架調(diào)用分析
在框架直接生成服務(wù)容器的只有一處,在bootstrap/app.php,通過require引用會返回服務(wù)容器實例。通過require引用有兩處,一處是public/index.php,服務(wù)器訪問的入口;另一處是tests/CreatesApplication.php,是單元測試的入口;
如果想在項目各處中調(diào)用,可以調(diào)用$app = IlluminateContainerContainer::getInstance()或者全局幫助函數(shù)app()獲取服務(wù)容器實例(也就是IlluminateFoundation/Application實例);
IlluminateFoundation/Application是對IlluminateContainerContainer的又一層封裝;
Application初始化
那么實例化IlluminateFoundation/Application時,做了什么呢?
第一步,設(shè)置應(yīng)用的根目錄,并同時注冊核心目錄到服務(wù)容器中;核心的目錄有以下
-
path:目錄app的位置
-
path.base:項目根目錄的位置
-
path.lang:目錄resources/lang的位置
-
path.config:目錄config的位置
-
path.public:目錄public的位置
-
path.storage:目錄storage的位置
-
path.database:目錄database的位置
-
path.resources:目錄resources的位置
-
path.bootstrap:目錄bootstrap的位置
第二步,將當(dāng)前IlluminateFoundation/Application實例保存到$instance類變量,并同時綁定到服務(wù)容器作單例綁定,綁定名為app或Container::class;
第三步,順序分別執(zhí)行注冊IlluminateEventsEventServiceProvider、IlluminateLogLogServiceProvider和IlluminateRoutingRoutingServiceProvider三個服務(wù)提供者;
注冊服務(wù)提供者的順序如下:
-
如果類變量$serviceProviders已經(jīng)存在該服務(wù)提供者并且不需要強制重新注冊,則返回服務(wù)提供者實例$provider;
-
未注冊過當(dāng)前服務(wù)提供者,則繼續(xù)執(zhí)行以下;
-
如果存在register方法,執(zhí)行服務(wù)提供者的register方法;
-
將當(dāng)前服務(wù)提供者$provider實例保存到類變量$serviceProviders數(shù)組中,同時標(biāo)記類變量$loadedProviders[get_class($provider)]的值為true;
-
判斷類變量$booted是否為true,如果是true,則執(zhí)行服務(wù)提供者的boot方法;(類變量$booted應(yīng)該是標(biāo)志是否所有服務(wù)提供者均注冊,框架是否啟動)
第四步,注冊核心類別名;
比如IlluminateFoundationApplication::class、IlluminateContractsContainerContainer::class起別名為app;
單元測試Application的bootstrap啟動分析
啟動代碼很簡潔,
Route::get('dev', 'Dev@index'); public function index() { // require 初始化分析上面已經(jīng)介紹了 $app = require base_path('bootstrap/app.php'); $kernel = $app->make('IlluminateContractsHttpKernel'); dd($kernel); }
構(gòu)造函數(shù)主要干了一件事,注冊一個booted完成后的回調(diào)函數(shù),函數(shù)執(zhí)行的內(nèi)容為“注冊 Schedule實例到服務(wù)提供者,同時加載用戶定義的Schedule任務(wù)清單”;
bootstrap方法的執(zhí)行內(nèi)容如下:
-
加載Illuminate/Foundation/Console/Kernel中$bootstrappers變量數(shù)組中的類,執(zhí)行它們的bootstrap方法;
-
protected?$bootstrappers?=?[ ????//?加載?.env?文件 ????IlluminateFoundationBootstrapLoadEnvironmentVariables::class, ????//?加載?config?目錄下的配置文件 ????IlluminateFoundationBootstrapLoadConfiguration::class, ????//?自定義錯誤報告,錯誤處理方法及呈現(xiàn) ????IlluminateFoundationBootstrapHandleExceptions::class, ????//?為?config/app.php?中的?aliases?數(shù)組注冊類別名 ????IlluminateFoundationBootstrapRegisterFacades::class, ????//?在服務(wù)容器中單例綁定一個?request?對象,控制臺命令會用到 ????IlluminateFoundationBootstrapSetRequestForConsole::class, ????//?注冊?configapp.php?中的?providers?服務(wù)提供者 ????IlluminateFoundationBootstrapRegisterProviders::class, ????//?項目啟動,執(zhí)行每個?ServiceProvider?的?boot?方法, ????IlluminateFoundationBootstrapBootProviders::class, ];
-
加載延遲的服務(wù)提供者;
Http訪問Application的bootstrap啟動分析
啟動入口文件在publicindex.php
$app = require_once __DIR__.'/../bootstrap/app.php'; // 實例化 Illuminate/Foundation/Http/Kernel 對象 $kernel = $app->make(IlluminateContractsHttpKernel::class); // 中間件處理、業(yè)務(wù)邏輯處理 $response = $kernel->handle( // 根據(jù) Symfony 的 request 對象封裝出 IlluminateHttpRequest $request = IlluminateHttpRequest::capture() ); $response->send(); // 執(zhí)行所有中間件的 terminate 方法,執(zhí)行 Application 中的 terminatingCallbacks 回調(diào)函數(shù) $kernel->terminate($request, $response);
重要的類變量數(shù)組
aliases數(shù)組
維護 類與別名 的數(shù)組;鍵名為 類的全限定類名,鍵值為 數(shù)組,每一個元素都是該類的別名;
判斷指定類是否有別名:app()->isAlias($name);
獲取指定類的別名:app()->getAlias($abstract);
abstractAliases數(shù)組
維護 類與別名 的數(shù)組;鍵名為 別名,鍵值為 類的全限定類名;
instances數(shù)組
維護 類與實例的數(shù)組;鍵名為 類的全限定類名,鍵值為該類的實例;
移除綁定類:app()->forgetInstance($abstract);
移除所有綁定類:app()->forgetInstances();
bindings數(shù)組
通過 bind 方法實現(xiàn) 接口類與實現(xiàn)的綁定;
獲取bindings數(shù)組中的內(nèi)容:app()->getBindings()
resolved數(shù)組
鍵名為 類的全限定類名,鍵值為布爾值類型(true表示已解析過,false表示未解析過);
with 數(shù)組
在resolved過程中,會有一些參數(shù);with數(shù)組就是參數(shù)棧,開始解析時將參數(shù)入棧,結(jié)束解析時參數(shù)出棧;
contextual數(shù)組
上下文綁定數(shù)組;第一維數(shù)組鍵名為 場合類(比如某個Controller類的類名),第二維數(shù)組鍵名為 抽象類(需要實現(xiàn)的接口類),鍵值為 Closure 或 某個具體類的類名;
tags數(shù)組
維護 標(biāo)簽與類 的數(shù)組;鍵名是 標(biāo)簽名,鍵值是 對應(yīng)要綁定的類的名稱;
如果調(diào)用tagged方法,會將鍵值數(shù)組中的類都make出來,并以數(shù)組形式返回;
extenders數(shù)組
在make或resolve出對象的時候,會執(zhí)行
foreach ($this->getExtenders($abstract) as $extender) { $object = $extender($object, $this);}
能對解析出來的對象進行修飾;
methodBindings數(shù)組
向容器綁定方法與及實現(xiàn):app()->bindMethod($method, $callback)
判斷容器內(nèi)是否有指定方法的實現(xiàn):app()->hasMethodBinding($method)
執(zhí)行方法的實現(xiàn):app()->callMethodBinding($method, $instance)或者app()->call($method)
buildStack數(shù)組
調(diào)用build方法時維護的棧,棧中存放的是當(dāng)前要new的類名;
reboundCallbacks數(shù)組
當(dāng)調(diào)用rebound函數(shù)時,會觸發(fā)rebound中為此$abstract設(shè)置的回調(diào)函數(shù);
注冊入口:app()->rebinding($abstract, Closure $callback);
serviceProviders數(shù)組
已在系統(tǒng)注冊的服務(wù)提供者ServiceProvider;
數(shù)組內(nèi)存放的是loadedProviders鍵名對應(yīng)類的實例;
loadedProviders數(shù)組
系統(tǒng)已加載的ServiceProvider的集合;鍵名為ServiceProvider的全限定類名,鍵值為布爾值(true表示已加載,false表示未加載);
獲取延遲加載對象:app()->getLoadedProviders();
deferredServices數(shù)組
有些服務(wù)提供者是會延遲加載的;這時候會將這些服務(wù)提供者聲明的服務(wù)登錄在deferredServices數(shù)組,鍵名為延遲加載對象名 ,鍵值為該延遲加載對象所在的ServiceProvider;
獲取延遲加載對象:app()->getDeferredServices();
bootingCallbacks數(shù)組
項目啟動前執(zhí)行的回調(diào)函數(shù);(項目啟動是在執(zhí)行IlluminateFoundationBootstrapBootProviders::class的時候)
注冊入口:app()->booting($callback);
bootedCallbacks數(shù)組
項目啟動后執(zhí)行的回調(diào)函數(shù);(項目啟動是在執(zhí)行IlluminateFoundationBootstrapBootProviders::class的時候)
注冊入口:app()->booted($callback);
resolvingCallbacks數(shù)組
解析時回調(diào)函數(shù)集合;鍵名為 類名, 鍵值為 回調(diào)函數(shù)數(shù)組,每一個元素都是回調(diào)函數(shù);
注冊入口:app()->resolving($abstract, $callback);
afterResolvingCallbacks數(shù)組
解析后回調(diào)函數(shù)集合;鍵名為 類名, 鍵值為 回調(diào)函數(shù)數(shù)組,每一個元素都是回調(diào)函數(shù);
注冊入口:app()->afterResolving($abstract, $callback);
globalResolvingCallbacks數(shù)組
全局解析時回調(diào)函數(shù)集合;每一次resolve方法調(diào)用時都會執(zhí)行的回調(diào)函數(shù)集合;
注冊入口:app()->resolving($callback);
globalAfterResolvingCallbacks數(shù)組
全局解析后回調(diào)函數(shù)集合;每一次resolve方法調(diào)用后都會執(zhí)行的回調(diào)函數(shù)集合;
注冊入口:app()->afterResolving($callback);
terminatingCallbacks數(shù)組
系統(tǒng)在返回response之后,會執(zhí)行terminate方法,來做應(yīng)用結(jié)束前的掃尾處理;
這個數(shù)組就是執(zhí)行terminate方法時會執(zhí)行的回調(diào)函數(shù)集合;
注冊入口:app()->terminating(Closure $callback);
常用方法的解析
bind方法
public function bind($abstract, $concrete = NULL, $shared = false)
第一個參數(shù)是要注冊的類名或接口名,第二個參數(shù)是返回類的實例的閉包(或類的實例類名),第三個參數(shù)是否是單例;
方法內(nèi)部流程:
-
unset 掉 instances 和 aliases 數(shù)組中鍵值為 $abstract 的元素;
-
如果 $concrete 值為 null ,將 $abstract 賦值給 $concrete;
-
如果 $concrete 不是 Closure 對象,則封裝成閉包;
-
將 $concrete 和 $shared 通過 compact,添加進 bindings 數(shù)組,鍵名為 $abstract;
-
判斷 $abstract 在 resolved 和 instances 數(shù)組中是否存在,如果存在,則執(zhí)行第 6 步;
-
觸發(fā) rebound回調(diào)函數(shù);如果 reboundCallbacks 數(shù)組中注冊以 $abstract 為鍵名的回調(diào)函數(shù),則執(zhí)行這些回調(diào)函數(shù);
涉及數(shù)組:instances和aliases(unset 操作)、bindings(add 操作)
singleton方法
單例綁定;
public function singleton($abstract, $concrete = null) $this->bind($abstract, $concrete, true);}
涉及數(shù)組:instances和aliases(unset 操作)、bindings(add 操作)
bindIf方法
單例綁定;
public function bindIf($abstract, $concrete = null, $shared = false) { if (! $this->bound($abstract)) { $this->bind($abstract, $concrete, $shared); } }
涉及數(shù)組:instances和aliases(unset 操作)、bindings(add 操作)
instance方法
綁定實例;
public function instance($abstract, $instance)
方法內(nèi)部流程:
-
如果$abstract在aliases數(shù)組中存在,則從abstractAliases中所有的值數(shù)組中移除該類;
-
unset 掉 aliases 數(shù)組中鍵名為 $abstract的元素;
-
賦值操作:$this->instances[$abstract] = $instance;
-
判斷 $abstract 在 resolved 和 instances 數(shù)組中是否存在,如果存在,則執(zhí)行第 5 步;
-
觸發(fā) rebound回調(diào)函數(shù);如果 reboundCallbacks 數(shù)組中注冊以 $abstract 為鍵名的回調(diào)函數(shù),則執(zhí)行這些回調(diào)函數(shù);
涉及數(shù)組:instances(add 操作)、aliases 和 abstractAliases(unset 操作)
make方法
public function make($abstract) { return $this->resolve($abstract);}
alias
給類起別名;
public function alias($abstract, $alias) { $this->aliases[$alias] = $abstract; $this->abstractAliases[$abstract][] = $alias; }
涉及數(shù)組:aliases和abstractAliases(add 操作)
laravel 的源代碼生命周期
第一步 Laravel 應(yīng)用的所有請求入口都是 public/index.php 文件。打開 index.php 發(fā)現(xiàn)代碼也就幾行。
下面我們來講一下每一句代碼的作用是什么?
// 定義了laravel一個請求的開始時間 define('LARAVEL_START', microtime(true)); // composer自動加載機制 require __DIR__.'/../vendor/autoload.php'; // 這句話你就可以理解laravel,在最開始引入了一個ioc容器。 $app = require_once __DIR__.'/../bootstrap/app.php'; // 打開__DIR__.'/../bootstrap/app.php';你會發(fā)現(xiàn)這段代碼,綁定了IlluminateContractsHttpKernel::class, // 這個你可以理解成之前我們所說的$ioc->bind();方法。 // $app->singleton( // IlluminateContractsHttpKernel::class, // AppHttpKernel::class // ); // 這個相當(dāng)于我們創(chuàng)建了Kernel::class的服務(wù)提供者 $kernel = $app->make(IlluminateContractsHttpKernel::class); // 獲取一個 Request ,返回一個 Response。以把該內(nèi)核想象作一個代表整個應(yīng)用的大黑盒子,輸入 HTTP 請求,返回 HTTP 響應(yīng)。 $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); // 就是把我們服務(wù)器的結(jié)果返回給瀏覽器。 $response->send(); // 這個就是執(zhí)行我們比較耗時的請求, $kernel->terminate($request, $response);
走到這里你會發(fā)現(xiàn),是不是在我們學(xué)會了 ioc,服務(wù)提供者理解起來就比較簡單了。那 $middleware,服務(wù)提供者都是在哪個文件注冊運行的呢?
打開 AppHttpKernel::class 這個文件,你會發(fā)現(xiàn)定義了一堆需要加載的 $middleware。這個 kernel 的主要方法還是在他的父類里面 IlluminateFoundationHttpKernel 中。
打開 IlluminateFoundationHttpKernel,你會發(fā)現(xiàn)定義了啟動時需要做的事呢?
protected $bootstrappers = [ IlluminateFoundationBootstrapLoadEnvironmentVariables::class, IlluminateFoundationBootstrapLoadConfiguration::class, IlluminateFoundationBootstrapHandleExceptions::class, IlluminateFoundationBootstrapRegisterFacades::class, IlluminateFoundationBootstrapRegisterProviders::class, IlluminateFoundationBootstrapBootProviders::class, ];
$bootstrappers 就定義了我們的 RegisterFacades.class,RegisterProviders.class 這兩個類的意思就是要將我們在 app.config 中的 Providers,Facades 注入到我們的 Ioc 容器中。
【相關(guān)推薦:laravel】