摘要:因?qū)嶋H項(xiàng)目需求,近日在開發(fā)包的時(shí)候,發(fā)現(xiàn)設(shè)置屬性設(shè)置為時(shí),會(huì)導(dǎo)致在方法中注冊(cè)的無(wú)效。研究源碼在中注冊(cè)無(wú)效,但是在其他中注冊(cè)有效,說(shuō)明是其他問(wèn)題。所以切記如果準(zhǔn)備采用延遲加載時(shí),嚴(yán)禁進(jìn)行注冊(cè)等系列操作。嚴(yán)禁在延遲加載的注冊(cè)和。
因?qū)嶋H項(xiàng)目需求,近日在開發(fā) laravel-database-logger 包的時(shí)候,發(fā)現(xiàn)設(shè)置 ServiceProvider defer 屬性設(shè)置為 true 時(shí),會(huì)導(dǎo)致在 register 方法中注冊(cè)的 middleware 無(wú)效。
class ServiceProvider extends IlluminateSupportServiceProvider { protected $defer = true; public function register() { $this->mergeConfigFrom( __DIR__ . "/../config/config.php", "ibrand.dblogger" ); $this->app->singleton(DbLogger::class, function ($app) { return new DbLogger(); }); //當(dāng) $defer 設(shè)置為 true 時(shí),在路由中引用 databaselogger middleware 會(huì)報(bào)錯(cuò),提示 databaselogger class not found. $this->app[IlluminateRoutingRouter::class]->middleware("databaselogger", Middleware::class); } public function provides() { return [DbLogger::class]; } }
當(dāng)問(wèn)題出現(xiàn)的時(shí)候就懷疑是因?yàn)樵O(shè)置了 defer 屬性設(shè)置為 true 導(dǎo)致的,立刻就修改源碼把 protected $defer = true; 的代碼注釋掉,結(jié)果仍然是提示 databaselogger class not found.,說(shuō)明 Laravel 并沒(méi)有注冊(cè)此 ServiceProvder
接下來(lái)就是想如何解決此問(wèn)題,嘗試了下面的方法:
1. 驗(yàn)證本身代碼是否存在問(wèn)題
在正常注冊(cè)的 AppServiceProvider 中注冊(cè)自己的 ServiceProvider
public function register() { // $this->app->register(IbrandDatabaseLoggerServiceProvider::class); }
注冊(cè)后結(jié)果一切正常。
2. 研究源碼
在 config/app.php 中 providers 注冊(cè)無(wú)效,但是在其他 ServiceProvider 中注冊(cè)有效,說(shuō)明是其他問(wèn)題。
通過(guò)研究 IlluminateFoundationApplication 源碼找到 registerConfiguredProviders 方法:
Laravel 是在此方法中去讀取 config/app.php 中的 providers 內(nèi)容并load到 ProviderRepository 中。
(new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath())) ->load($providers->collapse()->toArray());
重點(diǎn)在 $this->getCachedServicesPath() ,通過(guò)源碼發(fā)現(xiàn) Laravel 是根據(jù) bootstrap/cache/services.php 文件去決定如何注冊(cè) ServiceProvider。
此時(shí)想到了為什么之前注釋了 //protected $defer = true; 代碼后仍然無(wú)效的原因。
所以為了讓注釋后的 //protected $defer = true; 代碼有效需要執(zhí)行
php artisan clear-compiled php artisan optimize
之后問(wèn)題就解決了,也更加深入理解了 ServiceProvider 的原理。
所以切記:如果準(zhǔn)備采用延遲加載ServiceProvider時(shí),嚴(yán)禁進(jìn)行注冊(cè) middleware, route 等系列操作。同時(shí),更改 defer 屬性值后,需要執(zhí)行 php artisan clear-compiled 和 php artisan optimize 以更新 ServiceProvider 緩存。
3. 為什么 AppServiceProvider 中注冊(cè)有效?
愿意很簡(jiǎn)單,因?yàn)?AppServiceProvider 并沒(méi)有延遲加載,因此在執(zhí)行 AppServiceProvider 中 register 方法去注冊(cè)新的 ServiceProvider 也是不會(huì)延遲加載的。
總結(jié)謹(jǐn)慎使用延遲加載 ServiceProvider
更改 defer 屬性值后,需要執(zhí)行 php artisan clear-compiled 和 php artisan optimize 以更新 ServiceProvider 緩存。
嚴(yán)禁在延遲加載的 ServiceProvider 注冊(cè) middleware 和 route 。
討論交流文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/26285.html
摘要:調(diào)用了的可以看出,所有服務(wù)提供器都在配置文件文件的數(shù)組中。啟動(dòng)的啟動(dòng)由類負(fù)責(zé)引導(dǎo)應(yīng)用的屬性中記錄的所有服務(wù)提供器,就是依次調(diào)用這些服務(wù)提供器的方法,引導(dǎo)完成后就代表應(yīng)用正式啟動(dòng)了,可以開始處理請(qǐng)求了。 服務(wù)提供器是所有 Laravel 應(yīng)用程序引導(dǎo)中心。你的應(yīng)用程序自定義的服務(wù)、第三方資源包提供的服務(wù)以及 Laravel 的所有核心服務(wù)都是通過(guò)服務(wù)提供器進(jìn)行注冊(cè)(register)和引...
摘要:總結(jié)本文主要學(xué)習(xí)了啟動(dòng)時(shí)做的七步準(zhǔn)備工作環(huán)境檢測(cè)配置加載日志配置異常處理注冊(cè)注冊(cè)啟動(dòng)。 說(shuō)明:Laravel在把Request通過(guò)管道Pipeline送入中間件Middleware和路由Router之前,還做了程序的啟動(dòng)Bootstrap工作,本文主要學(xué)習(xí)相關(guān)源碼,看看Laravel啟動(dòng)程序做了哪些具體工作,并將個(gè)人的研究心得分享出來(lái),希望對(duì)別人有所幫助。Laravel在入口index...
摘要:實(shí)例化各服務(wù)提供者,根據(jù)其屬性將服務(wù)進(jìn)行分類延遲服務(wù)即時(shí)服務(wù),從而得到一個(gè)數(shù)組格式如,延遲處理注冊(cè)延遲的服務(wù),以后再進(jìn)行調(diào)用注冊(cè)延遲的事件即時(shí)處理直接進(jìn)行注冊(cè)調(diào)用等,并重新寫入到,然后根據(jù)此文件進(jìn)行相應(yīng)的處理。 Laravel Kernel引導(dǎo)流程分析 代碼展示 protected function sendRequestThroughRouter($request) { # ...
摘要:大家都知道項(xiàng)目寫起來(lái)是挺爽,但是在生產(chǎn)環(huán)境性能不高,我們來(lái)抽絲剝繭分析我自己項(xiàng)目的運(yùn)行時(shí)間消耗耗時(shí)步驟耗時(shí)觀察初步結(jié)論在調(diào)用和的方法時(shí),消耗時(shí)間是大頭。類是用于注冊(cè)服務(wù)提供者的。但此優(yōu)化在下無(wú)效。我們進(jìn)一步分析。 大家都知道 laravel 項(xiàng)目寫起來(lái)是挺爽,但是在生產(chǎn)環(huán)境性能不高,我們來(lái)抽絲剝繭分析我自己項(xiàng)目的運(yùn)行時(shí)間消耗: Bootstrap 耗時(shí) 步驟 耗時(shí) Illum...
摘要:說(shuō)明本文主要學(xué)習(xí)容器的實(shí)例化過(guò)程,主要包括等四個(gè)過(guò)程??聪碌脑创a如果是數(shù)組,抽取別名并且注冊(cè)到中,上文已經(jīng)討論實(shí)際上就是的。 說(shuō)明:本文主要學(xué)習(xí)Laravel容器的實(shí)例化過(guò)程,主要包括Register Base Bindings, Register Base Service Providers , Register Core Container Aliases and Set the ...
閱讀 3051·2021-11-16 11:45
閱讀 5423·2021-09-22 10:57
閱讀 1830·2021-09-08 09:36
閱讀 1701·2021-09-02 15:40
閱讀 2565·2021-07-26 23:38
閱讀 1304·2019-08-30 15:55
閱讀 992·2019-08-30 15:54
閱讀 1278·2019-08-29 14:06