首頁 > php框架 > Laravel > 主體

聊聊laravel中的Service Container

藏色散人
發布: 2021-07-27 08:57:03
轉載
2291 人瀏覽過

什麼是Service Container

The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.

從Laravel官方文件對於Service Container的解釋可以看出,它的作用就是幫助我們管理和進行依賴注入的。

為什麼要用Service Container

在《依賴注入》中,我們看到使用依賴注入可以極大的降低程式碼的耦合度,但是也帶來了一個缺點,就是需要自己管理注入的對象。
如果一個元件有很多依賴,我們需要創建多個參數的setter方法來傳遞依賴關係,或者建立一個多個參數的建構函數來傳遞它們,另外在使用元件前還要每次都創建依賴,這讓我們的程式碼像這樣不易維護。
所以為依賴實例提供一個容器(Service Container),就是一個實用且優雅的方法。
例如下面是laravel的入口檔案(已去掉註解):

// public/index.php
<?php

require __DIR__.&#39;/../bootstrap/autoload.php&#39;;

$app = require_once __DIR__.&#39;/../bootstrap/app.php&#39;;

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);
登入後複製
// bootstrap/app.php
<?php

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.&#39;/../&#39;)
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

return $app;
登入後複製

首先看bootstrap/app.php,其中$app Illuminate\Foundation\Application的一個實例,而Illuminate\Foundation\Application類別繼承自Container,所以$app其實就是一個Service Container。
然後下面的三個singleton方法定義了當依賴Illuminate\Contracts\Http\KernelIlluminate\Contracts\Console\KernelIlluminate\Contracts\Debug \ExceptionHandler這三個介面時,注入哪個類別的單例。
然後看public/index.php,其中的make方法其實就是用Service Container來new一個Illuminate\Contracts\Http\Kernel實例,跟普通new的差別就是會把他的依賴自動注入進去。

是不是很簡潔?

其實不單是Laravel,像是Yii2、Phalcon等框架都透過實作容器來管理依賴注入。

如何使用Service Container

既然是一個容器,無非就是兩個事,往裡面放東西和往外取東西,對應到Service Container就是綁定(Binding)和解析(Resolving )。

取得容器

在Laravel的Service Provider中,可以透過$this->app取得容器,除此之外,還可以使用app ()來取得容器。
如果在Laravel外使用Service Container,直接new一個Illuminate\Container\Container就可以獲得容器了。

以下都用$container代表取得到的容器。

綁定

  • 綁定傳回介面的實例

#
//使用闭包
$container->bind('BarInterface', function(){
    return new Bar();
});
//或者使用字符串
$container->bind('FooInterface', 'Foo');
登入後複製
  • ##綁定單例

singletion 方法綁定一個只會被解析一次的類別或介面到容器中,且後面的呼叫都會從容器中傳回相同的實例:

$container->singleton('BarInterface', function(){
    return new Bar();
});
登入後複製
  • 綁定實例

你也可以使用instance 方法,將一個已經存在的物件實例綁定到容器中。後面的呼叫都會從容器中回傳指定的實例:

$bar = new Bar();
$bar->setSomething(new Something);

$container->instance('Bar', $bar);
登入後複製
  • 情境綁定

有時候,你可能有兩個類別使用到相同接口,但你希望每個類別都能注入不同實作。

$container->when('Man')
          ->needs('PartnerInterface')
          ->give('Woman');
$container->when('Woman')
          ->needs('PartnerInterface')
          ->give('Man');
登入後複製
  • 標記

#有些時候,可能需要解析某個「分類」下的所有綁定。

$container->bind('Father', function () {
    //
});
$container->bind('Mother', function () {
    //
});
$container->bind('Daughter', function () {
    //
});
$container->bind('Son', function () {
    //
});
$container->tag(['Father', 'Mother', 'Daughter', 'Son'], 'familyMembers');

$container->bind('Family', function ($container) {
    return new Family($container->tagged('familyMembers'));
});
登入後複製
解析

  • make方法

  • #
$foo = $container->make('Foo');
登入後複製
  • 陣列方法

##
$bar = $container['Bar'];
登入後複製
  • 解析被標記綁定

$familyMembers = $container->tagged('familyMembers');

foreach ($familyMembers as $inpidual) {
    $inpidual->doSomething();
}
登入後複製

解析事件

每當服務容器解析一個物件時就會觸發事件。你可以使用 resolving 方法監聽這個事件。

$container->resolving(function ($object, $container) {
    // 当容器解析任何类型的对象时会被调用...
});

$container->resolving('Foo', function (Foo $foo, $container) {
    // 当容器解析「Foo」类型的对象时会被调用...
});
登入後複製

相關推薦:最新的五個Laravel影片教學

以上是聊聊laravel中的Service Container的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!