摘要:服務通過匿名函數定義,返回一個對象的實例定義一些服務請注意,匿名函數可以訪問當前容器實例,從而允許引用其他服務或參數。如果要為所有調用返回不同的實例,請使用方法包裝你的匿名函數。
鏈接
官網 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 PimpleContainer; $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; });
第一個參數是要擴展的服務的名稱,第二個參數是訪問對象實例和容器的函數。
擴展容器如果你反復使用相同的庫,可能希望將一個項目中的某些服務重用到下一個項目,通過實現 PimpleServiceProviderInterface 接口,打包你的服務到 Provider 程序中
use PimpleContainer; class FooProvider implements PimpleServiceProviderInterface { 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 容器類PimplePsr11Container 類允許你使用 PsrContainerContainerInterface 方法訪問 Pimple 容器的內容:
use PimpleContainer; use PimplePsr11Container 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 下注冊
use MonologLogger; use PimplePsr11ServiceLocator; use PsrContainerContainerInterface; use SymfonyComponentEventDispatcherEventDispatcher; class MyService { /** * "logger" must be an instance of PsrLogLoggerInterface * "event_dispatcher" must be an instance of SymfonyComponentEventDispatcherEventDispatcherInterface */ private $services; public function __construct(ContainerInterface $services) { $this->services = $services; } } $container["logger"] = function ($c) { return new MonologLogger(); }; $container["dispatcher"] = function () { return new EventDispatcher(); }; $container["service"] = function ($c) { $locator = new ServiceLocator($c, array("logger", "event_dispatcher" => "dispatcher")); return new MyService($locator); };懶懶的引用一系列服務
在數組中傳遞一組服務實例可能會導致效率低下,因為如果使用集合的類只需要在稍后調用它的方法時對其進行迭代即可。如果集合中存儲的其中一個服務與使用該服務的類之間存在循環依賴關系,則也會導致問題。
ServiceIterator 類可以幫助你解決這些問題。它在實例化過程中接收服務名稱列表,并在迭代時檢索服務
use PimpleContainer; use PimpleServiceIterator; 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
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/28634.html
摘要:現在我們就可以在構造函數或者任何其他通過服務容器注入依賴項的地方使用類型提示注入接口創建一個新的類實例,此處將注入的實例。自動解析構造函數所需的依賴的服務容器實現了接口。 簡單的服務容器 一個簡單的 php 5.3 依賴注入容器。 項目地址:https://github.com/godruoyi/easy-container Why 目前比較流行的 PHP 容器: Pimple La...
摘要:服務容器接口是的簡寫,由組織制定的規范,是開發的實踐標準。實現的容器類源碼很簡單,主要是傳入變量,然后設置這個兩個方法。原創文章,歡迎轉載。原文鏈接地址作者發表日期 接著上篇 還有一些內容沒有寫,上篇已經把關于 Pimple 最主要的代碼分析了一下,這篇主要是關于 PSR-11 兼容性的分析。 PSR-11 服務容器接口 PSR PSR 是 PHP Standard Recommend...
摘要:已經有了非常好的的相關解析,建議先看下一個簡單的依賴注入容器讀源碼筆記上讀源碼筆記下這里通過例子補充下核心方法的說明相關的類型服務類似單例工廠服務多個實例參數僅僅是保存一些變量保護參數匿名函數都會被認為服務,但是如果僅僅是想作為一個 已經有了非常好的Pimple的相關解析,建議先看下:Pimple - 一個簡單的 PHP 依賴注入容器讀 PHP - Pimple 源碼筆記(上)讀 PH...
摘要:控制反轉容器控制反轉使依賴注入變得更加便捷。有瑕疵控制反轉容器是實現的控制翻轉容器的一種替代方案。容器的獨立使用即使沒有使用框架,我們仍然可以在項目中使用安裝組件來使用的控制反轉容器。在沒有給定任何信息的情況下,容器是無法實例化相關依賴的。 聲明:本文并非博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當然也不是原汁原味...
摘要:代碼這就是控制反轉模式。是變量有默認值則設置默認值是一個類,遞歸解析有默認值則返回默認值從容器中取得以上代碼的原理參考官方文檔反射,具有完整的反射,添加了對類接口函數方法和擴展進行反向工程的能力。 PHP程序員如何理解依賴注入容器(dependency injection container) 背景知識 傳統的思路是應用程序用到一個Foo類,就會創建Foo類并調用Foo類的方法,假如這...
閱讀 807·2023-04-25 22:57
閱讀 3060·2021-11-23 10:03
閱讀 622·2021-11-22 15:24
閱讀 3164·2021-11-02 14:47
閱讀 2908·2021-09-10 11:23
閱讀 3127·2021-09-06 15:00
閱讀 3949·2019-08-30 15:56
閱讀 3332·2019-08-30 15:52