Laravel生命周期啟動(dòng)(從創(chuàng)建應(yīng)用實(shí)例到注冊(cè)基礎(chǔ)服務(wù))過(guò)程解析
引言
在了解了Laravle10大概的生命周期流程,從執(zhí)行到回調(diào)整個(gè)步驟,接下來(lái)我們來(lái)對(duì)其中的流程進(jìn)行詳細(xì)剖解來(lái)看一下它究竟是怎樣執(zhí)行的。
在入口文件中有一個(gè)步驟是
$app = require_once __DIR__.'/../bootstrap/app.php';
這樣的,它加載了bootstrap/app.php文件,那么這個(gè)文件究竟做了寫什么?我們一起往下看!
bootstrap/app.php都做了什么
創(chuàng)建應(yīng)用實(shí)例
第一行它是這樣的
/* |-------------------------------------------------------------------------- | Create The Application |-------------------------------------------------------------------------- | | The first thing we will do is create a new Laravel application instance | which serves as the "glue" for all the components of Laravel, and is | the IoC container for the system binding all of the various parts. |我們要做的第一件事是創(chuàng)建一個(gè)新的Laravel應(yīng)用程序?qū)嵗? |它作為L(zhǎng)aravel所有組件的“粘合劑”, |使系統(tǒng)綁定所有不同部分的IoC(控制反轉(zhuǎn))容器。 */ $app = new Illuminate\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__) );
意思就是說(shuō)此處創(chuàng)建了應(yīng)用實(shí)例,傳入了項(xiàng)目的基礎(chǔ)路徑,那么這個(gè)Application類里面又是怎樣的邏輯?讓我們往下看
Application的構(gòu)造方法: 在里面首先執(zhí)行了setBasePath方法,在里面設(shè)置了一些基本路徑
public function __construct($basePath = null) { if ($basePath) { $this->setBasePath($basePath); } $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); }
setBasePath設(shè)置了語(yǔ)言包、配置文件、靜態(tài)資源、view頁(yè)面、引導(dǎo)框架目錄、數(shù)據(jù)庫(kù)配置、日志緩存等基本路徑。
/** * Set the base path for the application. * * @param string $basePath * @return $this */ public function setBasePath($basePath) { $this->basePath = rtrim($basePath, '\/'); $this->bindPathsInContainer(); return $this; } /** * Bind all of the application paths in the container. * * @return void */ protected function bindPathsInContainer() { $this->instance('path', $this->path()); $this->instance('path.base', $this->basePath()); $this->instance('path.lang', $this->langPath()); $this->instance('path.config', $this->configPath()); $this->instance('path.public', $this->publicPath()); $this->instance('path.storage', $this->storagePath()); $this->instance('path.database', $this->databasePath()); $this->instance('path.resources', $this->resourcePath()); $this->instance('path.bootstrap', $this->bootstrapPath()); }
設(shè)置路徑通過(guò)instance函數(shù)進(jìn)行的,我們看一下instance函數(shù)。instance函數(shù)里面首先執(zhí)行了removeAbstractAlias方法,對(duì)傳入的變量進(jìn)行清空,即(path.base、path、path.lang)等,如果這些變量都存在的話,就把它們釋放刪除了。
public function instance($abstract, $instance) { $this->removeAbstractAlias($abstract); $isBound = $this->bound($abstract); unset($this->aliases[$abstract]); // We'll check to determine if this type has been bound before, and if it has // we will fire the rebound callbacks registered with the container and it // can be updated with consuming classes that have gotten resolved here. $this->instances[$abstract] = $instance; if ($isBound) { $this->rebound($abstract); } return $instance; } /** * Remove an alias from the contextual binding alias cache. * * @param string $searched * @return void */ protected function removeAbstractAlias($searched) { if (! isset($this->aliases[$searched])) { return; } foreach ($this->abstractAliases as $abstract => $aliases) { foreach ($aliases as $index => $alias) { if ($alias == $searched) { unset($this->abstractAliases[$abstract][$index]); } } } }
在instance第二行里面,調(diào)用了bound函數(shù),去確定給定的抽象類型是否已綁定,是否已被實(shí)例化,是否是別名。
$isBound = $this->bound($abstract); /** * Determine if the given abstract type has been bound. * * @param string $abstract * @return bool */ public function bound($abstract) { return isset($this->bindings[$abstract]) || isset($this->instances[$abstract]) || $this->isAlias($abstract); }
接著就是刪除別名
//刪除別名 unset($this->aliases[$abstract]);
把實(shí)例放到instances數(shù)組中
$this->instances[$abstract] = $instance;
最后根據(jù)第二行返回的$isBound的值去執(zhí)行rebound函數(shù),執(zhí)行到這里時(shí),項(xiàng)目所需要的instances實(shí)例就已經(jīng)加載完畢了,基礎(chǔ)路徑已經(jīng)全部加載完成了。
if ($isBound) { $this->rebound($abstract); } /** * Fire the "rebound" callbacks for the given abstract type. * * @param string $abstract * @return void */ protected function rebound($abstract) { $instance = $this->make($abstract); foreach ($this->getReboundCallbacks($abstract) as $callback) { call_user_func($callback, $this, $instance); } }
接著又增加了三個(gè)實(shí)例到instances數(shù)組內(nèi)
注冊(cè)基礎(chǔ)綁定
$this->registerBaseBindings();
把現(xiàn)有的實(shí)例注冊(cè)為實(shí)例中的共享容器
/** * Register the basic bindings into the container. * * @return void */ protected function registerBaseBindings() { static::setInstance($this); //1,調(diào)用靜態(tài)方法setInstance設(shè)置實(shí)例 $this->instance('app', $this); //2,調(diào)用Instance ,將現(xiàn)有的實(shí)例注冊(cè)為實(shí)例中的共享容器,查看Instance這個(gè)方法 (代碼instance,上面已經(jīng)說(shuō)過(guò)) //注冊(cè)app,Container $this->instance(Container::class, $this); //3,在容器中注冊(cè)mix獲取版本化的mix文件路徑 $this->singleton(Mix::class); $this->singleton(PackageManifest::class, function () { return new PackageManifest( new Filesystem, $this->basePath(), $this->getCachedPackagesPath() ); }); }
注冊(cè)基礎(chǔ)服務(wù)
$this->registerBaseServiceProviders();
查看registerBaseServiceProviders 注冊(cè)所有基本服務(wù)提供商
/** * Register all of the base service providers. * * @return void */ protected function registerBaseServiceProviders() { //注冊(cè)事件服務(wù) $this->register(new EventServiceProvider($this)); //注冊(cè)日志 $this->register(new LogServiceProvider($this)); //注冊(cè)路由 $this->register(new RoutingServiceProvider($this)); }
注冊(cè)容器別名
$this->registerCoreContainerAliases();
registerCoreContainerAliases 注冊(cè)核心容器別名
將一些重要的接口綁定到容器中我們將能夠在需要時(shí)解決它們
//http內(nèi)核 $app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class ); //console內(nèi)核 $app->singleton( Illuminate\Contracts\Console\Kernel::class, App\Console\Kernel::class ); //laravel的異常處理 $app->singleton( Illuminate\Contracts\Debug\ExceptionHandler::class, App\Exceptions\Handler::class );
到此app.php的內(nèi)容已經(jīng)解析完了。
以上就是Laravel生命周期啟動(dòng)(從創(chuàng)建應(yīng)用實(shí)例到注冊(cè)基礎(chǔ)服務(wù))過(guò)程解析的詳細(xì)內(nèi)容,更多關(guān)于Laravel生命周期的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TP3.2.3框架使用CKeditor編輯器在頁(yè)面中上傳圖片的方法分析
這篇文章主要介紹了TP3.2.3框架使用CKeditor編輯器在頁(yè)面中上傳圖片的方法,結(jié)合實(shí)例形式分析了thinkPHP3.2.3框架使用CKeditor編輯器相關(guān)配置方法與操作注意事項(xiàng),需要的朋友可以參考下2019-12-12用PHP寫的MySQL數(shù)據(jù)庫(kù)用戶認(rèn)證系統(tǒng)代碼
用PHP寫的MySQL數(shù)據(jù)庫(kù)用戶認(rèn)證系統(tǒng)代碼...2007-03-03Google Voice 短信發(fā)送接口PHP開(kāi)源版(2010.5更新)
Google Voice 短信發(fā)送接口PHP開(kāi)源版,以前的版本不能用了,作者于2010年5月進(jìn)行了更新。2010-07-07基于OpenCart 開(kāi)發(fā)支付寶,財(cái)付通,微信支付參數(shù)錯(cuò)誤問(wèn)題
使用OpenCart 開(kāi)發(fā)支付寶,財(cái)付通,微信支付如果稍不用心,很容易導(dǎo)致很多問(wèn)題,而這些錯(cuò)誤很有可能是參數(shù)傳遞錯(cuò)誤,下面小編給大家整理了一篇文章很不錯(cuò),在此分享給大家,感興趣的朋友一起看看吧2015-10-10yii2實(shí)現(xiàn) "上一篇,下一篇" 功能的代碼實(shí)例
在很多頁(yè)面上都需要加入上一篇,下一篇 按鈕,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02PHP dirname簡(jiǎn)單使用代碼實(shí)例
這篇文章主要介紹了PHP dirname簡(jiǎn)單使用代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11PHP全概率運(yùn)算函數(shù)(優(yōu)化版) Webgame開(kāi)發(fā)必備
PHP全概率運(yùn)算函數(shù)(優(yōu)化版) Webgame開(kāi)發(fā)必備,需要的朋友可以參考下。2011-07-07