Laravel 文檔 - 服務(wù)容器

簡介

  1. Laravel 服務(wù)容器是一個用于管理類的依賴和執(zhí)行依賴注入的強大工具盖淡。
  2. 依賴注入這個花哨名詞實質(zhì)上是指:類的依賴通過構(gòu)造函數(shù)债朵,或者某些情況下通過 "setter" 方法 "注入" 到類中圃庭。
  3. 這種注入方式的便利之處還體現(xiàn)在當我們?yōu)閼?yīng)用編寫測試時吏颖,我們還可以輕松地 "模擬" 或創(chuàng)建 UserRepository 的虛擬實現(xiàn)。

綁定

綁定基礎(chǔ)(不理解)

幾乎所有的服務(wù)容器綁定都是在 服務(wù)容器, 所以文檔中大多數(shù)例子都是使用了在服務(wù)提供器中綁定的容器季希。

簡單綁定

在服務(wù)提供器中褪那,你總是可以通過 $this->app 屬性訪問容器。我們可以通過容器的 bind 方法注冊綁定式塌,bind 方法的第一個參數(shù)為要綁定的類/接口名博敬,第二個參數(shù)是一個返回類實例的 Closure

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

綁定一個單例

singleton 方法將類或接口綁定到只解析一次的容器中。一旦單例綁定被解析峰尝,相同的對象實例會在隨后的調(diào)用中返回到容器中:

$this->app->singleton('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

綁定實例

你也可以使用 instance 方法將現(xiàn)有對象實例綁定到容器中偏窝。給定的實例會始終在隨后的調(diào)用中返回到容器中:

$api = new HelpSpot\API(new HttpClient);

$this->app->instance('HelpSpot\API', $api);

綁定基本值

當你有一個類不僅需要接受一個注入類,還需要注入一個基本值(比如整數(shù))武学。你可以使用上下文綁定來輕松注入你的類需要的任何值:

$this->app->when('App\Http\Controllers\UserController')
          ->needs('$variableName')
          ->give($value);

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

服務(wù)容器有一個很強大的功能祭往,就是支持綁定接口到給定的實現(xiàn)。例如火窒,如果我們有個 EventPusher 接口 和一個 RedisEventPusher 實現(xiàn)硼补。一旦我們寫完了 EventPusher 接口的 RedisEventPusher 實現(xiàn),我們就可以在服務(wù)容器中注冊它熏矿,像這樣:

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

這么做相當于告訴容器:當一個類需要實現(xiàn) EventPusher 時已骇,應(yīng)該注入 RedisEventPusher。現(xiàn)在我們就可以在構(gòu)造函數(shù)或者任何其他通過服務(wù)容器注入依賴項的地方使用類型提示注入 EventPusher 接口:

use App\Contracts\EventPusher;

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

上下文綁定

有時你可能有兩個類使用了相同的接口票编,但你希望各自注入不同的實現(xiàn)褪储。例如,有兩個控制器可能依賴了不同的 Illuminate\Contracts\Filesystem\Filesystem 契約 實現(xiàn)栏妖。Laravel 提供了一個簡單的乱豆,優(yōu)雅的接口來定義這個行為:

use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\PhotoController;
use App\Http\Controllers\VideoController;
use Illuminate\Contracts\Filesystem\Filesystem;

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('local');
          });

$this->app->when(VideoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('s3');
          });

標記

有時候奖恰,你可能需要解析某個 "分類" 下的所有綁定吊趾。例如:你正在構(gòu)建一個報表的聚合器宛裕,它接收一個包含不同 Report 接口實現(xiàn)的數(shù)組。注冊了 Report 實現(xiàn)之后论泛,你可以使用 tag 方法為它們分配標簽:

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

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

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

一旦服務(wù)被標記揩尸,你就可以使用 tagged 方法輕松將它們?nèi)拷馕觯?/p>

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

擴展綁定

extend 方法可以修改已解析的服務(wù)。例如屁奏,當一個服務(wù)被解析后岩榆,你可以添加額外的代碼去修飾或配置這個服務(wù)。extend 方法接受一個閉包坟瓢,該閉包唯一參數(shù)就是這個服務(wù)勇边,并返回修改過的服務(wù):

$this->app->extend(Service::class, function($service) {
    return new DecoratedService($service);
});

解析實例

make 方法

你可以使用 make 方法從容器中解析出類實例。make 方法接受一個你想要解析的類名或接口名:

$api = $this->app->make('HelpSpot\API');

如果你的代碼處于無法訪問 $app 變量的位置折联,則可用全局輔助函數(shù) resolve 來解析:

$api = resolve('HelpSpot\API');

如果你的類依賴不能通過容器來解析粒褒,你可以通過將它們作為關(guān)聯(lián)數(shù)組傳遞到 makeWith 方法來注入它們:

$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);

自動注入

另外,并且更重要的是诚镰,你可以簡單地使用"類型提示"的方式在類的構(gòu)造函數(shù)中注入那些需要容器解析的依賴項奕坟,包括 控制器, 事件監(jiān)聽器, 隊列任務(wù), 中間件等。實際上清笨,這才是大多數(shù)對象應(yīng)該被容器解析的方式月杉。

容器事件

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

$this->app->resolving(function ($object, $app) {
    // Called when container resolves object of any type...
});

$this->app->resolving(HelpSpot\API::class, function ($api, $app) {
    // Called when container resolves objects of type "HelpSpot\API"...
});

被解析的對象將被傳入回調(diào)函數(shù)抠艾,這使得你能夠在對象被傳給調(diào)用者之前給它設(shè)置額外的屬性苛萎。

PSR-11

Laravel 的服務(wù)容器實現(xiàn)了 PSR-11 接口。 因此检号,你可以使用 PSR-11容器『接口類型提示』來獲取 Laravel 容器的實例:

use Psr\Container\ContainerInterface;

Route::get('/', function (ContainerInterface $container) {
    $service = $container->get('Service');

    //
});

{note} 如果標識符還沒有被顯式綁定到容器首懈,那么調(diào)用 get 方法將會拋出異常。

總結(jié)
這一篇目前沒理解到什么東西啊谨敛,回頭要看

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末究履,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子脸狸,更是在濱河造成了極大的恐慌最仑,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炊甲,死亡現(xiàn)場離奇詭異泥彤,居然都是意外死亡,警方通過查閱死者的電腦和手機卿啡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門吟吝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颈娜,你說我怎么就攤上這事剑逃≌阋耍” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵蛹磺,是天一觀的道長粟瞬。 經(jīng)常有香客問我,道長萤捆,這世上最難降的妖魔是什么裙品? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮俗或,結(jié)果婚禮上市怎,老公的妹妹穿的比我還像新娘。我一直安慰自己辛慰,他們只是感情好焰轻,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著昆雀,像睡著了一般辱志。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狞膘,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天揩懒,我揣著相機與錄音,去河邊找鬼挽封。 笑死已球,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的辅愿。 我是一名探鬼主播智亮,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼点待!你這毒婦竟也來了阔蛉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤癞埠,失蹤者是張志新(化名)和其女友劉穎状原,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苗踪,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡颠区,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了通铲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毕莱。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朋截,到底是詐尸還是另有隱情蛹稍,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布质和,位于F島的核電站稳摄,受9級特大地震影響稚字,放射性物質(zhì)發(fā)生泄漏饲宿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一胆描、第九天 我趴在偏房一處隱蔽的房頂上張望瘫想。 院中可真熱鬧,春花似錦昌讲、人聲如沸国夜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽车吹。三九已至,卻和暖如春醋闭,著一層夾襖步出監(jiān)牢的瞬間窄驹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工证逻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乐埠,地道東北人。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓囚企,卻偏偏與公主長得像丈咐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子龙宏,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容