99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

架構(gòu) ―― 服務(wù)容器

2018-02-24 15:38 更新

架構(gòu) —— 服務(wù)容器

1、簡介

Laravel服務(wù)容器是一個用于管理類依賴和執(zhí)行依賴注入的強大工具。依賴注入聽上去很花哨,其實質(zhì)是通過構(gòu)造函數(shù)或者某些情況下通過set方法將類依賴注入到類中。

讓我們看一個簡單的例子:

<?php

namespace App\Jobs;

use App\User;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Bus\SelfHandling;

class PurchasePodcast implements SelfHandling{
    /**
     *?郵件實現(xiàn)
     */
    protected $mailer;

    /**
     *?創(chuàng)建一個新的實例
     *
     * @param  Mailer  $mailer
     * @return void
     */
    public function __construct(Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    /**
     *?購買一個播客
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

在本例中,當播客被購買后PurchasePodcast任務(wù)需要發(fā)送郵件,因此,你需要注入一個可以發(fā)送郵件的服務(wù)。由于該服務(wù)是被注入的,我們可以方便的使用其另一個實現(xiàn)來替換它,在測試的時候我們還可以”模擬“或創(chuàng)建一個假的郵件實現(xiàn)。

深入理解Laravel服務(wù)容器對于構(gòu)建功能強大的大型Laravel應(yīng)用而言至關(guān)重要,對于貢獻代碼到Laravel核心也很有幫助。

2、綁定

幾乎所有的服務(wù)容器綁定都是在服務(wù)提供者中完成。因此本章節(jié)的演示例子用到的容器都是在這種上下文環(huán)境中,如果一個類沒有基于任何接口那么就沒有必要將其綁定到容器。容器并不需要被告知如何構(gòu)建對象,因為它會使用PHP的反射服務(wù)自動解析出具體的對象。

在一個服務(wù)提供者中,可以通過$this->app變量訪問容器,然后使用bind方法注冊一個綁定,該方法需要兩個參數(shù),第一個參數(shù)是我們想要注冊的類名或接口名稱,第二個參數(shù)是返回類的實例的閉包:

$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app['HttpClient']);
});

注意到我們接受容器本身作為解析器的一個參數(shù),然后我們可以使用該容器來解析我們正在構(gòu)建的對象的子依賴。

綁定一個單例

singleton方法綁定一個只需要解析一次的類或接口到容器,然后接下來對容器的調(diào)用將會返回同一個實例:

$this->app->singleton('FooBar', function ($app) {
    return new FooBar($app['SomethingElse']);
});

綁定實例

你還可以使用instance方法綁定一個已存在的對象實例到容器,隨后對容器的調(diào)用將總是返回給定的實例:

$fooBar = new FooBar(new SomethingElse);

$this->app->instance('FooBar', $fooBar);

2.1 綁定接口到實現(xiàn)

服務(wù)容器的一個非常強大的特性是其綁定接口到實現(xiàn)的能力。我們假設(shè)有一個EventPusher接口及其RedisEventPusher實現(xiàn),編寫完該接口的RedisEventPusher實現(xiàn)后,就可以將其注冊到服務(wù)容器:

$this->app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');

這段代碼告訴容器當一個類需要EventPusher的實現(xiàn)時將會注入RedisEventPusher,現(xiàn)在我們可以在構(gòu)造器或者任何其它通過服務(wù)容器注入依賴的地方進行EventPusher接口的類型提示:

use App\Contracts\EventPusher;

/**
 *?創(chuàng)建一個新的類實例
 *
 * @param  EventPusher  $pusher
 * @return void
 */
public function __construct(EventPusher $pusher){
    $this->pusher = $pusher;
}

2.2 上下文綁定

有時侯我們可能有兩個類使用同一個接口,但我們希望在每個類中注入不同實現(xiàn),例如,當系統(tǒng)接到一個新的訂單的時候,我們想要通過PubNub而不是Pusher發(fā)送一個事件。Laravel定義了一個簡單、平滑的方式來定義這種行為:

$this->app->when('App\Handlers\Commands\CreateOrderHandler')
          ->needs('App\Contracts\EventPusher')
          ->give('App\Services\PubNubEventPusher');

你甚至還可以傳遞一個閉包到give方法:

$this->app->when('App\Handlers\Commands\CreateOrderHandler')
          ->needs('App\Contracts\EventPusher')
          ->give(function () {
                  // Resolve dependency...
              });

2.3?標簽

少數(shù)情況下我們需要解析特定分類下的所有綁定,比如,也許你正在構(gòu)建一個接收多個不同Report接口實現(xiàn)的報告聚合器,在注冊完Report實現(xiàn)之后,可以通過tag方法給它們分配一個標簽:

$this->app->bind('SpeedReport', function () {
    //
});

$this->app->bind('MemoryReport', function () {
    //
});

$this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');

這些服務(wù)被打上標簽后,可以通過tagged方法來輕松解析它們:

$this->app->bind('ReportAggregator', function ($app) {
    return new ReportAggregator($app->tagged('reports'));
});

3、解析

有很多方式可以從容器中解析對象,首先,你可以使用make方法,該方法接收你想要解析的類名或接口名作為參數(shù):

$fooBar = $this->app->make('FooBar');

其次,你可以以數(shù)組方式訪問容器,因為其實現(xiàn)了PHP的ArrayAccess接口:

$fooBar = $this->app['FooBar'];

最后,也是最常用的,你可以簡單的通過在類的構(gòu)造函數(shù)中對依賴進行類型提示來從容器中解析對象,包括控制器、事件監(jiān)聽器、隊列任務(wù)、中間件等都是通過這種方式。在實踐中,這是大多數(shù)對象從容器中解析的方式。

容器會自動為其解析類注入依賴,比如,你可以在控制器的構(gòu)造函數(shù)中為應(yīng)用定義的倉庫進行類型提示,該倉庫會自動解析并注入該類:

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use App\Users\Repository as UserRepository;

class UserController extends Controller{
    /**
     *?用戶倉庫實例
     */
    protected $users;

    /**
     *?創(chuàng)建一個控制器實例
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    /**
     *?通過指定ID顯示用戶
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        //
    }
}

4、容器事件

服務(wù)容器在每一次解析對象時都會觸發(fā)一個事件,可以使用resolving方法監(jiān)聽該事件:

$this->app->resolving(function ($object, $app) {
    //?容器解析所有類型對象時調(diào)用
});

$this->app->resolving(function (FooBar $fooBar, $app) {
    //?容器解析“FooBar”對象時調(diào)用
});

正如你所看到的,被解析的對象將會傳遞給回調(diào),從而允許你在對象被傳遞給消費者之前為其設(shè)置額外屬性。

擴展閱讀:實例教程——深入理解控制反轉(zhuǎn)和依賴注入

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號