摘要:在服務提供者內部,這個工作被稱之為服務容器綁定,綁定處理由服務提供者完成。通過服務提供者綁定服務是服務容器綁定服務的正確打開方式。為了完成注冊服務提供者的功能,僅需要將類名加入到配置文件的節點。此時,僅需簡單的調整下服務提供者中的代碼。
這是一篇翻譯文章,譯文首發于 Laravel 服務提供者指南,轉載請注明出處。
如果你使用過 Laravel 框架的話,那么,你不可能沒聽說過服務容器和服務提供者。事實上,它們是 Lavavel 框架核心,它們完成 Larvel 應用中服務啟動的艱巨任務。
在這篇文章中,我們將簡單介紹「服務容器」,同時還會深入講解服務提供者。本教程還將演示如何在 Laravel 中創建一個自定義的服務提供者。另外,如果你需要在 Laravel 中成功使用服務容器,還需要注冊它。那么,讓我們開始吧。
實現一個自定義的服務提供者,需要實現兩個非常重要的方法:boot 和 register 方法。關于這兩個方法將在教程最后一個小節討論。
在學習服務提供者之前,簡單介紹一下服務容器,服務容器會在服務提供者中被經常使用。
理解服務容器和服務提供者 什么是服務容器簡而言之,Laravel 服務容器 是一個用于存儲綁定組件的盒子,它還會為應用提供所需的服務。
Laravel 文檔中描述如下:
Laravel 服務容器是用于管理類的依賴和執行依賴注入的工具 - Laravel 文檔
這樣,當我們需要注入一個內置的組件或服務時,可以在構造函數或方法中使用類型提示功能注入,然后在使用時從服務容器中自動解析出所需實例及其依賴!是不是很酷?這個功能可以讓我們從手動管理組件中解脫出來,從而降低系統耦合度。
讓我們看一個簡單實例來加深理解。
如你所見,SomeClass 需要使用 FooBar 實例。換句話說它需要依賴其它組件。Laravel 實現自動注入需要從服務容器中查找并執行注入適當的依賴。
如果你希望了解 Laravel 是如何知道需要將哪個組件或服務綁定到服務容器中的,答案是通過服務提供者實現的。服務提供者完成將組件綁定到服務容器的工作。在服務提供者內部,這個工作被稱之為服務容器綁定,綁定處理由服務提供者完成。
服務提供者實現了服務綁定,綁定處理則由 register 方法完成。
同時,這又會引入一個新的問題:Laravel 是如何知道有哪些服務提供者的呢?這個我們貌似還沒有討論到吧?我到時看到,之前有說 Laravel 會自動的去查找到服務!朋友,你的問題太多了:Laravel 只是一個框架,它不是一個超級英雄,不是么?我們當然需要去明確的告知 Laravel 框架我們有哪些服務提供者。
讓我們來瞧瞧 config/app.php 配置文件。你會找到一個用于 Laravel 應用啟動過程中被載入的服務提供者配置列表。
"providers" => [ /* * Laravel Framework Service Providers... */ IlluminateAuthAuthServiceProvider::class, IlluminateBroadcastingBroadcastServiceProvider::class, IlluminateBusBusServiceProvider::class, IlluminateCacheCacheServiceProvider::class, IlluminateFoundationProvidersConsoleSupportServiceProvider::class, IlluminateCookieCookieServiceProvider::class, IlluminateDatabaseDatabaseServiceProvider::class, IlluminateEncryptionEncryptionServiceProvider::class, IlluminateFilesystemFilesystemServiceProvider::class, IlluminateFoundationProvidersFoundationServiceProvider::class, IlluminateHashingHashServiceProvider::class, IlluminateMailMailServiceProvider::class, IlluminateNotificationsNotificationServiceProvider::class, IlluminatePaginationPaginationServiceProvider::class, IlluminatePipelinePipelineServiceProvider::class, IlluminateQueueQueueServiceProvider::class, IlluminateRedisRedisServiceProvider::class, IlluminateAuthPasswordsPasswordResetServiceProvider::class, IlluminateSessionSessionServiceProvider::class, IlluminateTranslationTranslationServiceProvider::class, IlluminateValidationValidationServiceProvider::class, IlluminateViewViewServiceProvider::class, /* * Package Service Providers... */ LaravelTinkerTinkerServiceProvider::class, /* * Application Service Providers... */ AppProvidersAppServiceProvider::class, AppProvidersAuthServiceProvider::class, // AppProvidersBroadcastServiceProvider::class, AppProvidersEventServiceProvider::class, AppProvidersRouteServiceProvider::class, ],以上就是有關服務容器的基本概念。下一節,我們將焦點聚集到服務提供者這個核心主題上!
什么是服務提供者如果說服務容器是提供綁定和依賴注入的的工具,那么 服務提供者 則是實現綁定的工具。
讓我們先來看一個內容提供的服務提供者服務來理解它的運行原理。打開 vender/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php 文件。
public function register() { $this->app->singleton("cache", function ($app) { return new CacheManager($app); }); $this->app->singleton("cache.store", function ($app) { return $app["cache"]->driver(); }); $this->app->singleton("memcached.connector", function () { return new MemcachedConnector; }); }這里我們需要將重點集中在 register 方法中,這個方法用于綁定服務到服務容器。如你所見,這里一共執行了三個服務的綁定處理:cache、cache.store 和 memcached.connector。
然后,當我們需要在 Laravel 中使用 cache 服務是,服務容器會解析出 CacheManager 實例并返回。也就是說我們僅僅是提供了一個可以從 $this->app 訪問的對應關系表。
通過服務提供者綁定服務是 Laravel 服務容器綁定服務的正確打開方式。同時通過服務提供者的 register 方法,還有利于理解 Laravel 服務容器是如何管理所有的服務的。我們之前提到過,通過從 config/app.php 配置文件中讀取服務提供者配置列表,從將所有服務注冊服務容器中。
以上,就是服務提供者和它的故事。下一節,我們會學習如何創建一個服務提供者來實現將自己的服務注冊到 Laravel 服務容器。
自定義服務提供者Laravel 已經內置了一個用于創建服務提供者的 artisan 命令來簡化創建流程。進入命令行模式后執行下面命令來創建服務提供者。
php artisan make:provider EnvatoCustomServiceProvider運行后會在 app/Providers 目錄下創建 EnvatoCustomServiceProvider.php 文件。打開該文件看下它的源碼。
之前我們有提到服務提供者有兩個重要方法:boot 和 register 方法,在實現自定義服務提供者時大部分都是在處理這兩個方法。
register 方法用于執行服務綁定處理。另外在 boot 方法中可以使用所有已綁定的服務。在這個教程的最后一節我們將學習更多有關這兩個方法的細節,但在這里我們會先了解些這兩個方法的使用示例加深理解。
注冊自定義服務提供者前面我們創建了一個自定義的服務提供者。接下來需要讓 Laravel 知道如何讓這個服務提供者同其它服務提供者一樣在應用啟動時被加載到 Laravel 中。
為了完成注冊服務提供者的功能,僅需要將類名加入到 config/app.php 配置文件的 providers 節點。
"providers" => [ /* * Laravel Framework Service Providers... */ IlluminateAuthAuthServiceProvider::class, IlluminateBroadcastingBroadcastServiceProvider::class, IlluminateBusBusServiceProvider::class, IlluminateCacheCacheServiceProvider::class, IlluminateFoundationProvidersConsoleSupportServiceProvider::class, IlluminateCookieCookieServiceProvider::class, IlluminateDatabaseDatabaseServiceProvider::class, IlluminateEncryptionEncryptionServiceProvider::class, IlluminateFilesystemFilesystemServiceProvider::class, IlluminateFoundationProvidersFoundationServiceProvider::class, IlluminateHashingHashServiceProvider::class, IlluminateMailMailServiceProvider::class, IlluminateNotificationsNotificationServiceProvider::class, IlluminatePaginationPaginationServiceProvider::class, IlluminatePipelinePipelineServiceProvider::class, IlluminateQueueQueueServiceProvider::class, IlluminateRedisRedisServiceProvider::class, IlluminateAuthPasswordsPasswordResetServiceProvider::class, IlluminateSessionSessionServiceProvider::class, IlluminateTranslationTranslationServiceProvider::class, IlluminateValidationValidationServiceProvider::class, IlluminateViewViewServiceProvider::class, /* * Package Service Providers... */ LaravelTinkerTinkerServiceProvider::class, /* * Application Service Providers... */ AppProvidersAppServiceProvider::class, AppProvidersAuthServiceProvider::class, // AppProvidersBroadcastServiceProvider::class, AppProvidersEventServiceProvider::class, AppProvidersRouteServiceProvider::class, AppProvidersEnvatoCustomServiceProvider::class, ],就是如此簡單,現在你已經將自定義服務提供者注冊到了 Laravel 中。只不過現在這個服務提供者還幾乎什么都沒有處理。下一節,我們將以實例演示如何使用 register 和 boot 方法。
深入講解 register 和 boot 方法起先,我們來深入研究 register 方法加深你對這個方法的理解。打開之前創建的 app/Providers/EnvatoCustomServiceProvider.php 文件,加入如下代碼。
app->bind("AppLibraryServicesDemoOne", function ($app) { return new DemoOne(); }); } }這里我們做了兩個處理:
引入需要使用的 AppLibraryServicesDemoOne 服務。DemoOne 類現在還沒有創建,但之后會創建這個類。
在 register 方法中,我們使用服務容器的 bind 方法將服務綁定到容器。這樣,當需要使用 AppLibraryServicesDemoOne 服務而被解析時,就回調用閉包方法,創建實例并返回 AppLibraryServicesDemoOne 對象。
現在創建 app/Library/Services/DemoOne.php 文件。
然后,在控制器的構造函數中注入依賴。
doSomethingUseful(); } }以上便是一個使用綁定的簡單方法。事實上,對于這個示例其實并不需要創建一個服務提供者,并實現 register 方法,因為 Laravel 還可以通過 PHP 的方式功能自動解析。
Laravel 文檔中對此有一個說明:
如果我們的依賴無需任何接口,則無需將類綁定到容器。容器此時不需要了解創建對象的具體細節,而可以通過反射功能實現自動注入。換句話說,如果我們需要綁定的服務依賴于其它接口,創建服務提供者則很有必要。接著來看一個實例以加深理解。
首先,創建一個簡單的接口 app/Library/Services/Contracts/CustomServiceInterface.php。
然后,創建兩個基于此接口的具體實現。或者說,創建兩個繼承此接口的實現類。
一個是定義在 app/Library/Services/DemoOne.php 文件中的 DemoOne 類。
類似的,還有 app/Library/Services/DemoTwo.php。
現在,將綁定具體類名修改為綁定接口。打開 EnvatoCustomServiceProvider.php 文件并改成如何代碼。
app->bind("AppLibraryServicesContractsCustomServiceInterface", function ($app) { return new DemoOne(); }); } }這里,我們將 DemoOne 實現類綁定到 AppLibraryServicesContractsCustomServiceInterface 接口。后續,所有依賴 AppLibraryServicesContractsCustomServiceInterface 接口的功能都被解析成 AppLibraryServicesDemoOne 對象。 這個示例是不是更有實際意義呢?
當然,我們還需要調整下控制器中的代碼。
doSomethingUseful(); } }或許你已經猜到 $customServiceInstance 對象是 AppLibraryServicesDemoOne 類的實例!這種方案的優勢在于可以很容易的替換掉 DemoOne 這個實現。
假如你想使用 DemoTwo 替換掉 DemoOne 服務。此時,僅需簡單的調整下服務提供者中的代碼 EnvatoCustomServiceProvider.php。
將:
use AppLibraryServicesDemoOne;替換成:
use AppLibraryServicesDemoTwo;然后替換:
return new DemoOne();到:
return new DemoTwo();使用同樣的手法甚至可以將自定義的實現替換掉任何核心服務中的依賴。不僅如此,除了 bind 方法;Laravel 服務容器還提供多種綁定方法。可以查看 Laravel 服務容器 文檔了解更多。
下一個主題是可以擴展 Laravel 核心服務的 boot 方法。在這個方法中,你可以獲取所有通過服務提供者注冊到容器中的服務。通常,你會在這個方法中注冊某些功能完成后需要觸發其它操作的事件監聽器。
依照慣例看幾個示例先。
創建一個用于 Laravel 校驗的自定義表單驗證器。
public function boot() { Validator::extend("my_custom_validator", function ($attribute, $value, $parameters, $validator) { // validation logic goes here... }); }也許你想創建一個 view composer。在 boot 方法中創建是個不錯的選擇。
public function boot() { View::composer( "demo", "AppHttpViewComposersDemoComposer" ); }當然在這里需要率先導入 IlluminateSupportFacadesView。
有時,我們還需要創建一些共享數據。
public function boot() { View::share("key", "value"); }甚至可以顯示的創建模型綁定。
public function boot() { parent::boot(); Route::model("user", AppUser::class); }這些示例演示了 boot 方法的一些用法。只有更深入的理解,才能掌握它的使用方法!
與此同時,我們需要說再見了。我希望你喜歡本文所討論的主題。
結論本文討論的是服務提供者,這是本文的中心思想,盡管我們是以服務容器作為開篇,因為它是理解服務提供者的重要組成部分。
隨后,我們創建了一個自定義服務提供者,并且在本文的后半部分中,我們介紹了幾個實際的示例。
原文: How to Register & Use Laravel Service Providers
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28753.html
摘要:簡述的生命周期采用了單一入口模式,應用的所有請求入口都是文件。分發請求一旦應用完成引導和所有服務提供者都注冊完成,將會移交給路由進行分發。此外,由于對動態方法的獨特用法,也使測試起來非常容易。 本書的 GitHub 地址:https://github.com/todayqq/PH... Laravel 作為現在最流行的 PHP 框架,其中的知識較多,所以單獨拿出來寫一篇。 簡述 La...
摘要:通過添加此功能,該程序包將啟用記錄請求和響應信息所需的功能。是一條普通控制器路由,用于輸出控制臺的視圖。收集瀏覽器行為這是整個擴展包最乏味的部分。 Laravel Dusk 控制臺是一款 Laravel 擴展包,能夠為你的 Dusk 測試套件提供漂亮的可視面板。通過它,你可以可視化運行 Dusk 測試時涉及的各個步驟,以及查看每個步驟的 DOM 快照。這對于調試瀏覽器測試、并搞清楚后臺...
showImg(https://segmentfault.com/img/bV6aHV?w=1280&h=800); 社區優秀文章 Laravel 5.5+passport 放棄 dingo 開發 API 實戰,讓 API 開發更省心 - 自造車輪。 API 文檔神器 Swagger 介紹及在 PHP 項目中使用 - API 文檔撰寫方案 推薦 Laravel API 項目必須使用的 8 個...
摘要:現在面向所有人正式發布了。并且有計劃將作為可選擴展包發布,你仍然可以在項目中使用它們。是最新的穩定版本,將在年月左右處理收到的錯誤修復和更新,并在年月左右之前進行安全修復。中文翻譯中文翻譯已啟動,請關注更多翻譯文章請見開發者社區 showImg(https://segmentfault.com/img/remote/1460000018318895?w=1680&h=859); Lar...
摘要:我是沒有目錄,在項目根目錄下運行即可報錯這個是應用程序級錯誤,先開模式它在中,自己搜,改為即可然后就可以看到具體錯誤,我這邊是么有初始密碼,這個通過命令行可以解決。如果你有什么問題和疑惑關于首次安裝并運行,歡迎留言一起探討。 本指南目標在于指導萌新開啟第一步(我也是第一步——第N次卡在第一步) 初次運行報錯 報錯:500 查看Apache日志后終于解決,如果報500錯誤,就去查看服務...
閱讀 2270·2021-09-28 09:36
閱讀 2023·2021-09-22 15:14
閱讀 3632·2019-08-30 12:47
閱讀 3041·2019-08-30 12:44
閱讀 1236·2019-08-29 17:06
閱讀 541·2019-08-29 14:12
閱讀 981·2019-08-29 14:01
閱讀 2584·2019-08-29 12:17