簡單的服務容器
一個簡單的 php 5.3
依賴注入容器。
專案地址:https://github.com/godruoyi/easy-container
Why
目前比較流行的 PHP
容器:
Pimple
是一個簡單優秀的 php 5.3
容器,也是目前用得最多的服務容器,在 packagist 的安裝量也達到 1000 w+
。但是 Pimple
只是一個簡單的服務容器,不支援很多特性如:
class Cache
{
public function __construct(Config $config){}
}
class Config
{
}
// 不支援
$cache = $container->make('Cache');
Pimple 不支援自動注入依賴引數,當你需要的物件依賴其他物件時,你只能依次例項化所需引數。
Laravel Container
是目前功能最全的服務容器了,支援的功能也比較全面,包括自動注入、賴載入、別名、TAG等。但是官方不推薦在非 laravel
專案中使用該元件。
如果你有留意該元件下的
composer.json
檔案,你會發現他依賴 illuminate/contracts 元件。(參見)
基於此,誕生了 easy-container,該專案程式碼大部分依賴於 Laravel Container :smile:。你可以像使用 Laravel Container
容器般來使用它。
安裝
composer require godruoyi/easy-container
使用
你可以前往 Laravel-china 獲取更多關於 容器使用 的幫助。
初始化容器
$app = new Godruoyi\Container\Container;
以下文件支援來自 laravel-china,轉載請註明出處。
簡單繫結
可以通過 bind
方法註冊繫結,傳遞我們想要註冊的類或介面名稱再返回類的例項的 Closure
:
$app->bind('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
注意,所有匿名函式都接受服務容器例項作為引數。
繫結一個單例
singleton
方法將類或介面繫結到只能解析一次的容器中。繫結的單例被解析後,相同的物件例項會在隨後的呼叫中返回到容器中:
$app->singleton('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
每次呼叫
$app['HelpSpot\API']
都將返回統一物件。
繫結例項
你也可以使用 instance
方法將現有物件例項繫結到容器中。給定的例項會始終在隨後的呼叫中返回到容器中:
$api = new HelpSpot\API(new HttpClient);
$app->instance('HelpSpot\API', $api);
繫結介面到實現
服務容器有一個強大的功能,就是將介面繫結到給定實現。例如,如果我們有一個 EventPusher
介面和一個 RedisEventPusher
實現。編寫完介面的 RedisEventPusher
實現後,我們就可以在服務容器中註冊它,像這樣:
$app->bind(
'App\Contracts\EventPusher',
'App\Services\RedisEventPusher'
);
這麼做相當於告訴容器:當一個類需要實現 EventPusher
時,應該注入 RedisEventPusher
。現在我們就可以在建構函式或者任何其他通過服務容器注入依賴項的地方使用型別提示注入 EventPusher
介面:
use App\Contracts\EventPusher;
/**
* 建立一個新的類例項,此處將注入 App\Services\RedisEventPusher 的例項。
*
* @param EventPusher $pusher
* @return void
*/
public function __construct(EventPusher $pusher)
{
$this->pusher = $pusher;
}
解析
make
方法
你可以使用 make
方法將容器中的類例項解析出來 (無論該物件需要什麼型別的引數)。make
方法接受要解析的類或介面的名稱:
$api = $app->make('HelpSpot\API');
mark
方法是我認為最重要的方法,你可以簡單地使用「型別提示」的方式在由容器解析的類的建構函式中新增依賴項,容器將自動解析你所需要的一切引數。
// 自動解析UserController建構函式所需的依賴
$userController = $app->make(UserController::class);
class UserController
{
public function __construct(UserRepository $users, HttpClient $client, $other = 'default')
{
}
}
PSR-11
Laravel 的服務容器實現了 PSR-11 介面。因此,你可以對 PSR-11容器介面型別提示來獲取 Laravel 容器的例項:
use Psr\Container\ContainerInterface;
$service = $app->get('Service');
LISTEN
MIT