Pimple - 一个简单的 PHP 依赖注入容器
官網 WebSite
GitHub - Pimple 這是 Pimple 3.x 的文檔。如果你正在使用 Pimple 1.x ,請查看 Pimple 1.x 文檔。
閱讀 Pimple 1.x 代碼也是學習更多關于如何創建簡單的依賴注入容器的好方法,新版本的 Pimple 更加關注性能。
Pimple - 一個簡單的 PHP 依賴注入容器
安裝
在你的項目中使用 Pimple 之前,將其添加到你的 composer.json 文件中:
$ ./composer.phar require pimple/pimple ~3.0
另外,Pimple 也可作為 PHP C 擴展使用:
$ git clone https://github.com/silexphp/Pimple $ cd Pimple/ext/pimple $ phpize $ ./configure $ make $ make install使用
創建一個容器實例
use Pimple\Container;$container = new Container();與許多其他依賴注入容器一樣,Pimple 管理兩種不同類型的數據:服務和參數
定義服務
服務是一個對象,它可以作為一個龐大系統的一部分,一些服務的例子:數據庫連接,模板引擎,郵件服務。幾乎所有的全局對象都可以成為一項服務。
服務通過匿名函數定義,返回一個對象的實例
// 定義一些服務 $container['session_storage'] = function ($c) {return new SessionStorage('SESSION_ID'); };$container['session'] = function ($c) {return new Session($c['session_storage']); };請注意,匿名函數可以訪問當前容器實例,從而允許引用其他服務或參數。
由于只有在獲取對象時才創建對象,因此定義的順序無關緊要。
使用定義的服務也非常簡單:
// 獲取 session 對象 $session = $container['session'];// 上述調用大致等同于以下代碼: // $storage = new SessionStorage('SESSION_ID'); // $session = new Session($storage);定義工廠服務
默認情況下,每次獲得服務時,Pimple 都會返回相同的實例。如果要為所有調用返回不同的實例,請使用 factory() 方法包裝你的匿名函數。
$container['session'] = $container->factory(function ($c) {return new Session($c['session_storage']); });現在,每次調用 $container['session'] 會返回一個新的 session 實例。
定義參數
定義參數允許從外部簡化容器的配置并存儲全局值
// 定義一些參數 $container['cookie_name'] = 'SESSION_ID'; $container['session_storage_class'] = 'SessionStorage';你現在可以很輕松的通過重寫 session_storage_class 參數而不是重新定義服務定義來更改 cookie 名稱。
保護參數
由于 Pimple 將匿名函數看作服務定義,因此需要使用 protect() 方法將匿名函數包裝為參數:
$container['random_func'] = $container->protect(function () {return rand(); });修改已經定義的服務
在某些情況下,你可能需要在定義服務定義后修改它。在你的服務被創建后,你可以使用 extend() 方法添加額外的代碼:
$container['session_storage'] = function ($c) {return new $c['session_storage_class']($c['cookie_name']); };$container->extend('session_storage', function ($storage, $c) {$storage->...();return $storage; });第一個參數是要擴展的服務的名稱,第二個參數是訪問對象實例和容器的函數。
擴展容器
如果你反復使用相同的庫,可能希望將一個項目中的某些服務重用到下一個項目,通過實現 Pimple\ServiceProviderInterface 接口,打包你的服務到 Provider 程序中
use Pimple\Container;class FooProvider implements Pimple\ServiceProviderInterface {public function register(Container $pimple){// register some services and parameters// on $pimple} }然后,在容器上注冊 Provider
$pimple->register(new FooProvider());獲取服務創建方法
當你訪問一個對象時,Pimple 自動調用你定義的匿名函數,為你創建服務對象。如果你想獲得這個函數的原始訪問權限,你可以使用 raw()方法:
$container['session'] = function ($c) {return new Session($c['session_storage']); };$sessionFunction = $container->raw('session');PSR-11 兼容性
由于歷史原因,Container 類沒有實現 PSR-11 ContainerInterface。然而,Pimple 提供了一個輔助類,它可以讓你從 Pimple 容器類中解耦你的代碼
PSR-11 容器類
Pimple\Psr11\Container 類允許你使用 Psr\Container\ContainerInterface 方法訪問 Pimple 容器的內容:
use Pimple\Container; use Pimple\Psr11\Container as PsrContainer;$container = new Container(); $container['service'] = function ($c) {return new Service(); }; $psr11 = new PsrContainer($container);$controller = function (PsrContainer $container) {$service = $container->get('service'); }; $controller($psr11);使用 PSR-11 服務定位
有時候,服務需要訪問其他幾個服務,而不必確定所有這些服務都將被實際使用。在這些情況下,你可能希望懶加載這些服務。
傳統的解決方案是注入整個服務容器來獲得真正需要的服務。但是,這不被推薦,因為它使服務對應用程序的其他部分的訪問過于寬泛,并且隱藏了它們的實際依賴關系。
ServiceLocator 旨在通過訪問一組預定義的服務來解決此問題,同時僅在實際需要時才實例化它們。
它還允許你以不同于用于注冊的名稱提供服務。例如,你可能希望使用一個對象,該對象期望 EventDispatcherInterface 實例在名稱 event_dispatcher 下可用,而你的事件分派器已在名稱 dispatcher 下注冊
懶懶的引用一系列服務
在數組中傳遞一組服務實例可能會導致效率低下,因為如果使用集合的類只需要在稍后調用它的方法時對其進行迭代即可。如果集合中存儲的其中一個服務與使用該服務的類之間存在循環依賴關系,則也會導致問題。
ServiceIterator 類可以幫助你解決這些問題。它在實例化過程中接收服務名稱列表,并在迭代時檢索服務
use Pimple\Container; use Pimple\ServiceIterator;class AuthorizationService {private $voters;public function __construct($voters){$this->voters = $voters;}public function canAccess($resource){foreach ($this->voters as $voter) {if (true === $voter->canAccess($resource) {return true;}}return false;} }$container = new Container();$container['voter1'] = function ($c) {return new SomeVoter(); } $container['voter2'] = function ($c) {return new SomeOtherVoter($c['auth']); } $container['auth'] = function ($c) {return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2')); }誰在支持 Pimple ?
Pimple 是由 Symfony 框架的創建者 Fabien Potencier 寫的 ,Pimple 是在 MIT 協議下發布的。
原創文章,歡迎轉載。轉載請注明出處,謝謝。原文鏈接地址:http://dryyun.com/2018/04/17/...
作者: dryyun
發表日期: 2018-04-17 14:30:29
總結
以上是生活随笔為你收集整理的Pimple - 一个简单的 PHP 依赖注入容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过xadmin或者suit-v2快速搭
- 下一篇: ES-PHP向ES批量添加文档报No a