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