關(guān)于Laravel Service Provider開發(fā)設(shè)置延遲加載時遇到的問題詳解
前言
本文主要介紹了關(guān)于Laravel Service Provider設(shè)置延遲加載時遇到的一些問題,之所有這篇文章,是因?qū)嶋H項目需求,近日在開發(fā) laravel-database-logger 包的時候,發(fā)現(xiàn)設(shè)置 ServiceProvider defer 屬性設(shè)置為 true 時,會導(dǎo)致在 register 方法中注冊的 middleware 無效。
class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
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 時,在路由中引用 databaselogger middleware 會報錯,提示 databaselogger class not found.
$this->app[\Illuminate\Routing\Router::class]->middleware('databaselogger', Middleware::class);
}
public function provides()
{
return [DbLogger::class];
}
}
當(dāng)問題出現(xiàn)的時候就懷疑是因為設(shè)置了 defer 屬性設(shè)置為 true 導(dǎo)致的,立刻就修改源碼把 protected $defer = true; 的代碼注釋掉,結(jié)果仍然是提示 databaselogger class not found. ,說明 Laravel 并沒有注冊此 ServiceProvder
接下來就是想如何解決此問題,嘗試了下面的方法:
1. 驗證本身代碼是否存在問題
在正常注冊的 AppServiceProvider 中注冊自己的 ServiceProvider
public function register()
{
//
$this->app->register(\Ibrand\DatabaseLogger\ServiceProvider::class);
}
注冊后結(jié)果一切正常。
2. 研究源碼
在 config/app.php 中 providers 注冊無效,但是在其他 ServiceProvider 中注冊有效,說明是其他問題。
通過研究 Illuminate\Foundation\Application 源碼找到 registerConfiguredProviders 方法:
Laravel 是在此方法中去讀取 config/app.php 中的 providers 內(nèi)容并load到 ProviderRepository 中。
(new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
->load($providers->collapse()->toArray());
重點在 $this->getCachedServicesPath() ,通過源碼發(fā)現(xiàn) Laravel 是根據(jù) bootstrap/cache/services.php 文件去決定如何注冊 ServiceProvider。
此時想到了為什么之前注釋了 //protected $defer = true; 代碼后仍然無效的原因。
所以為了讓注釋后的 //protected $defer = true; 代碼有效需要執(zhí)行
php artisan clear-compiled php artisan optimize
之后問題就解決了,也更加深入理解了 ServiceProvider 的原理。
所以切記:如果準(zhǔn)備采用延遲加載ServiceProvider時,嚴(yán)禁進(jìn)行注冊 middleware, route 等系列操作。同時,更改 defer 屬性值后,需要執(zhí)行 php artisan clear-compiled 和 php artisan optimize 以更新 ServiceProvider 緩存。
3. 為什么 AppServiceProvider 中注冊有效?
愿意很簡單,因為 AppServiceProvider 并沒有延遲加載,因此在執(zhí)行 AppServiceProvider 中 register 方法去注冊新的 ServiceProvider 也是不會延遲加載的。
總結(jié)
謹(jǐn)慎使用延遲加載 ServiceProvider
更改 defer 屬性值后,需要執(zhí)行 php artisan clear-compiled 和 php artisan optimize 以更新 ServiceProvider 緩存。
嚴(yán)禁在延遲加載的 ServiceProvider 注冊 middleware 和 route 。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
對象失去焦點時自己動提交數(shù)據(jù)的實現(xiàn)代碼
生產(chǎn)線上,提升輸入員輸入效率,在沒有購買到Bar code槍之前,需要修改程序,即是說當(dāng)mouse光標(biāo)離開TextBox之后,數(shù)據(jù)自動提交到數(shù)據(jù)庫中2012-11-11
php mssql 分頁SQL語句優(yōu)化 持續(xù)影響
經(jīng)過SQL優(yōu)化后的分面查詢速度能夠得到大幅提高。2009-04-04
DW中鏈接mysql數(shù)據(jù)庫時,建立字符集中文出現(xiàn)亂碼的解決方法
DW中鏈接mysql數(shù)據(jù)庫時,建立字符集中文出現(xiàn)亂碼“????”2010-03-03
從一個不錯的留言本弄的mysql數(shù)據(jù)庫操作類
本文通過實例代碼給大家介紹了mysql數(shù)據(jù)庫操作類的相關(guān)知識,感興趣的朋友跟隨腳本之家小編一起看看吧2007-09-09
刪除html標(biāo)簽得到純文本可處理嵌套的標(biāo)簽
這篇文章主要介紹了通過刪除html標(biāo)簽得到的純文本可處理嵌套的標(biāo)簽,需要的朋友可以參考下2014-04-04

