合約
#簡潔性
契約 Vs. Facades
Laravel 的 Facades 和輔助函數提供了一種簡單方式來使用 Laravel 服務而無需用到類型提示,也可在服務容器外部解析契約。多數情況下,每個 Facade 都有一個等效的契約。
和 Facades (不須要在你類別中的建構子去引用依賴)不同的是,契約允許你給自己的類別定義明確的依賴。有些開發者喜歡依賴被明確定義出來,所以更傾向於使用契約,而其他開發者則享受於 Facades 帶來的方便。
{tip} 在大多數應用中,無論你喜歡 Facades 或契約,都是沒問題的。然而如果你在搭建擴充包,那你應該強烈考慮使用契約,因為他們更便於在套件的上下文中做測試。
何時使用契約
綜上所述,使用契約還是Facades 很大程度上取決於你個人或團隊的喜好。契約和 Facades 都可以用來建構健壯的、充分測試過的 Laravel 應用。只要你保持類別的職責單一,你會發現使用契約和 Facades 的實際差異是非常小的。
然而,你以也許仍有許多關於契約的問題。比方說,為啥都用 interface ?用 interface 不是更複雜嗎?讓我們在接下來的內容(「低耦合」與「簡潔性」)中,提煉出原因。
#低耦合
#首先,讓我們來看一些快取實作的高耦合程式碼。假設有下面程式碼:
<?php namespace App\Orders; class Repository{ /** * 缓存实例. */ protected $cache; /** * 创建一个新的仓库实例. * * @param \SomePackage\Cache\Memcached $cache * @return void */ public function __construct(\SomePackage\Cache\Memcached $cache) { $this->cache = $cache; } /** * 根据 ID 获取订单. * * @param int $id * @return Order */ public function find($id) { if ($this->cache->has($id)) { // } } }
在這個類別中,程式碼與給定的快取實作形成高度耦合。它的高度耦合是因為我們依賴了一個擴充包中特定的快取類別。如果該擴充包的 API 變了,那麼我們的程式碼也將必須做出修改。
同理,如果我們想要將底層的快取技術 ( Memcached ) 替換成另一種快取技術 ( Redis ),我們得再次修改我們的程式碼庫。我們的程式碼庫不應該對誰提供的資料或資料是怎麼提供的有太多了解。
我們可以透過依賴一個簡單的與擴充包無關的interface 來改進我們的程式碼,來取代先前的實作方式:
<?php namespace App\Orders; use Illuminate\Contracts\Cache\Repository as Cache; class Repository{ /** * 缓存实例. */ protected $cache; /** * 创建一个新的仓库实例. * * @param Cache $cache * @return void */ public function __construct(Cache $cache) { $this->cache = $cache; } }
現在的程式碼不與任何特定的擴充包耦合了,甚至與Laravel 都是無關的。由於契約擴充包不包含任何實作和依賴,你可以輕鬆地為給定的契約編寫替代實現的程式碼,從而可以在不修改任何快取程式碼的情況下替換快取的實作。
簡單
當 Laravel 的所有服務都在簡單的介面中整齊定義時,很容易透過給定的服務確定提供的功能。 契約充當框架功能的簡潔性文件。
此外,當你依賴簡單的介面時,你的程式碼更容易理解和維護。你可以參考一個簡單,乾淨的接口,而不是在大型複雜的類別中追蹤哪些方法是可用的。
如何使用契約
那麼,你要如何實現一個契約呢?它實際上很簡單。
Laravel 中的許多類型的類別透過 服務容器 來解析,包括控制器,事件偵聽,中間件,佇列作業,甚至路由閉包等。那麼,要取得一個合約的實現,你只需在要解析的類別的構造方法中鍵入『類型提示』的介面。
例如,看看這個事件偵聽器:
<?php namespace App\Listeners; use App\User;use App\Events\OrderWasPlaced; use Illuminate\Contracts\Redis\Factory; class CacheOrderInformation{ /** * Redis 工厂实现。 */ protected $redis; /** * 创建一个新的事件处理器实例。 * * @param Factory $redis * @return void */ public function __construct(Factory $redis) { $this->redis = $redis; } /** * 处理事件。 * * @param OrderWasPlaced $event * @return void */ public function handle(OrderWasPlaced $event) { // } }
當事件偵聽器被解析時,服務容器將讀取類別的建構方法上的類型提示,並注入適當的值。若要了解更多有關在服務容器中註冊的內容,請查看 服務容器文件。
合約參考
此表提供了所有 Laravel 契約及其等效 facades 的一個快速參考:
Contract | References Facade |
---|---|
#Illuminate\Contracts\Auth\Access \可授權 | ##|
Gate |
|
# | |
## | ##Illuminate\Contracts\Auth\Factory |
Auth |
| Illuminate\Contracts\Auth\Guard
Auth::guard() |
| #Illuminate\Contracts\Auth\PasswordBroker
Password::broker() |
|
Illuminate\Contracts\Auth\PasswordBrokerFactory | |
密碼 | ##Illuminate\Contracts\Auth\StatefulGuard |
##Illuminate\Contracts\Auth\SupportsBasicAuth | |
## | |
#Illuminate\Contracts\Auth\UserProvider | ##
|
Bus | |
Illuminate\Contracts\Bus\QueueingDispatcher | ##Bus::dispatchToQueue() |
照亮\合約\廣播\工廠 | 「廣播
|
#################################################### # #Illuminate\Contracts\Broadcasting\Broadcaster############Broadcast::connection()###################Illuminate\Contracts\Broadcasting \應該廣播### | |
##照亮\合約\廣播\ShouldBroadcastNow | #|
##Illuminate\Contracts\Cache\Factory | Cache |
##Illuminate\Contracts\Cache\Lock | |
##照亮\Contracts\Cache\LockProvider | |
#Illuminate\Contracts\Cache\Repository | #Cache::driver()
|
Illuminate\ Contracts\Cache \Store | #|
Illuminate\Contracts\Config\Repository | #Config
|
Illuminate\Contracts\Console\Application | |
#Illuminate \Contracts\Console \Kernel | Artisan
|
Illuminate\Contracts\Container\Container | #App
|
Illuminate\Contracts\Cookie\Factory | ##Cookie |
Cookie::queue() |
|
##Crypt | |
Event |
|
##Storage::cloud() |
| 照亮\合約\檔案系統\工廠##儲存
|
照亮\合約\檔案系統\檔案系統 | 存儲:: disk()
|
Illuminate\Contracts\Foundation\Application |
|
| |
Hash | |
## Illuminate\Contracts \Http\Kernel |
|
#Mail ::隊列() | |
Illuminate\Contracts\Mail\Mailable |
|
| |
通知 |
|
##通知 | |
Illuminate\Contracts\Pagination\LengthAwarePaginator | #|
##Illuminate\Contracts \Pagination\Paginator## | |
##Illuminate\Contracts\Pipeline\Hub | # |
Illuminate\Contracts\Pipeline\Pipeline | #
|
| |
########隊列########## #########Illuminate\Contracts\Queue\Job######### ######################################################################### ##Illuminate\Contracts\Queue\Monitor### ########隊列###################合約\隊列\佇列########################################################### | ##Queue::connection()
|
#Illuminate\Contracts\Queue\QueueableCollection | #|
照亮\合約\佇列\QueueableEntity | #|
照亮\合約\隊列\ShouldQueue | |
#Illuminate\Contracts\Redis\Factory | #Redis
|
Illuminate\Contracts\Routing\BindingRegistrar | Route
|
#Illuminate\Contracts\Routing\Registrar | Route
|
##Illuminate\Contracts\Routing \ResponseFactory | 回應
|
#Illuminate\Contracts\Routing\UrlGenerator | URL
|
Illuminate\Contracts\Routing\UrlRoutable | |
##Illuminate\Contracts \Session\Session | #Session::driver()
|
Illuminate\Contracts\ Support\Arrayable | |
Illuminate\Contracts\Support\Htmlable | ##|
#Illuminate\Contracts\Support\Jsonable | #|
#Illuminate\Contracts\Support\MessageBag##Illuminate\Contracts\Support\MessageBag | |
#。 | |
######Illuminate\Contracts\Support\MessageProvider######### ############# ####Illuminate\Contracts\Support \可渲染######### ##############照亮\合約\支援\負責################################################################################################################### #### ######## #######Illuminate\Contracts\Translation\Loader#### | |
##Illuminate\Contracts\Translation\Translator | ##Lang
|
Validator |
|
## | 照亮\Contracts\Validation\Rule |
##Illuminate\Contracts\Validation\ValidatesWhenResolved | |
#Illuminate\Contracts\Validation\Validator | |
Illuminate\Contracts\Validation\Validator | ##Validator::make()
|
#」 |
|
|