粉刺/粉刺

Pimple,一个简单的依赖注入容器

安装:101003994

受抚养人:1631

建议者:50

安全性:0

星星:2626

观察者:103

叉子:310

第3.5.0版 2021-10-28 11:13 UTC

自述文件

注意安全

Pimple现在关闭以进行更改。不会添加任何新功能,也不会接受任何外观更改。唯一可以接受的更改是与较新PHP版本的兼容性和安全问题修复。

注意安全

这是Pimple 3.x的文档。如果您使用Pimple 1.x,请阅读Pimple 1.x文档。阅读Pimple 1.x代码也是了解如何创建简单依赖注入容器的好方法(Pimple的最新版本更关注性能)。

Pimple是一个用于PHP的小型依赖注入容器。

安装

在项目中使用Pimple之前,请将其添加到作曲家.json文件:

$ ./composer.phar需要粉刺/粉刺"^3.0"

用法

创建容器就是创建一个集装箱实例:

使用 粉刺\集装箱;$容器=新的 集装箱();

与许多其他依赖注入容器一样,Pimple管理两种不同类型的数据:服务参数.

定义服务

服务是作为更大系统的一部分执行某些操作的对象。服务示例:数据库连接、模板引擎或邮件程序。几乎所有全球的对象可以是服务。

服务定义如下匿名函数返回对象实例的:

//定义一些服务
$容器['会话存储']=fn($c(c))=>新的 会话存储(“SESSION_ID”);$容器[“会话”]=fn($c(c))=>新的 会话($c(c)['会话存储']);

注意,匿名函数可以访问当前容器实例,允许引用其他服务或参数。

由于对象仅在获得时创建,因此定义的顺序无关紧要。

使用定义的服务也很容易:

//获取会话对象
$阶段=$容器[“会话”];//上述调用大致相当于以下代码:
//$storage=新会话存储('SESSION_ID');
//$session=新会话($storage);

定义工厂服务

默认情况下,每次获得服务时,Pimple都会返回同一实例如果希望为所有调用返回不同的实例,请使用工厂()方法

$容器[“会话”] =$容器->工厂(fn)($c(c))=>新的 会话($c(c)['会话存储']));

现在,每次呼叫$container[“会话”]返回会话的新实例。

定义参数

定义参数可以简化容器的外部配置并存储全局值:

//定义一些参数
$容器['厨师名称'] =“SESSION_ID”;$容器['会话存储类'] =“会话存储”;

如果您更改会话存储服务定义如下:

$容器['会话存储']=fn($c(c))=>新的 $c(c)['会话存储类']($c(c)['厨师名称']);

现在可以通过覆盖厨师_名称参数,而不是重新定义服务定义。

保护参数

因为Pimple将匿名函数视为服务定义,所以需要用保护()方法将其存储为参数:

$容器['random_func'] =$容器->保护(fn()=>rand());

定义后修改服务

在某些情况下,您可能希望在定义服务定义后对其进行修改。您可以使用扩展()方法来定义创建服务后要在其上运行的其他代码:

$容器['会话存储']=fn($c(c))=>新的 $c(c)['会话存储类']($c(c)['厨师名称']);$容器->延伸('会话存储',功能($存储,$c(c)) {$存储->...();返回 $存储;});

第一个参数是要扩展的服务的名称,第二个参数是访问对象实例和容器的函数。

扩展容器

如果你反复使用相同的库,你可能想在一个项目到下一个项目中重用一些服务;将您的服务打包到供应商通过实施Pimple\服务提供者接口:

使用 粉刺\集装箱; Foo提供商 实施 皮普尔\服务提供商接口{公众的 功能 登记(容器 $粉刺){//注册一些服务和参数
        //在$pimple上}}

然后,在容器上注册提供程序:

$粉刺->登记(新的 Foo提供商());

获取服务创建函数

当您访问对象时,Pimple会自动调用您定义的匿名函数,该函数会为您创建服务对象。如果要获取对此函数的原始访问权限,可以使用raw()方法:

$容器[“会话”]=fn($c(c))=>新的 会话($c(c)['会话存储']);$session函数=$容器->未经加工的(“会话”);

PSR-11兼容性

出于历史原因集装箱类不实现PSR-11容器接口但是,Pimple提供了一个帮助器类,可以将代码与Pimple容器类解耦。

PSR-11容器类

这个Pimple\Psr11\容器类允许您使用Psr\Container\Container接口方法:

使用 粉刺\集装箱;使用 粉刺\压力等级11\集装箱 作为 Psr容器;$容器=新的 集装箱();$容器['服务']=fn($c(c))=>新的 服务();$第11页=新的 Psr容器($容器);$控制器=功能(Psr容器 $容器) {$服务=$容器->得到('服务');};$控制器($功率因数11);

使用PSR-11 ServiceLocator

有时,一个服务需要访问其他几个服务,而不必确保所有服务都会被实际使用。在这些情况下,您可能希望服务的实例化是惰性的。

传统的解决方案是注入整个服务容器以仅获得真正需要的服务。然而,不建议这样做,因为它使服务对应用程序的其余部分具有太广泛的访问权限,并且隐藏了它们的实际依赖性。

这个服务定位器旨在通过提供对一组预定义服务的访问权限,同时仅在实际需要时实例化这些服务来解决此问题。

它还允许您使用不同于注册名称的名称提供服务。例如,您可能希望使用需要实例的对象事件调度器接口以该名称提供事件发送器当您的事件调度器已在名称下注册时调度员:

使用 独白\记录器;使用 粉刺\压力等级11\服务定位器;使用 磅/平方英寸\集装箱\容器接口;使用 Symfony公司\组件\事件调度器\事件调度器; 我的服务{/**
*“logger”必须是Psr\Log\LoggerInterface的实例
*“event_dispatcher”必须是Symfony\Component\EventDispatcher\EventDispatcherInterface的实例
*/
    私有的 $服务;公众的 功能 __构造(容器接口 $服务){$->服务=$服务;}}$容器[“记录器”]=fn($c(c))=>新的 独白\记录器();$容器[“调度程序”]=fn($c(c))=>新的 事件调度程序();$容器['服务'] =功能($c(c)) {$定位器=新的 服务定位器($c(c),阵列(“记录器”,'事件发送器'=>“调度程序”));返回 新的 我的服务($定位器);};

延迟引用服务集合

如果使用集合的类只需要在稍后调用其方法之一时对其进行迭代,那么在数组中传递服务实例集合可能会被证明是低效的。如果集合中存储的某个服务与使用该服务的类之间存在循环依赖关系,也会导致问题。

这个服务迭代器类帮助您解决这些问题。它在实例化期间接收服务名称列表,并在迭代时检索服务:

使用 粉刺\集装箱;使用 粉刺\服务迭代器; 授权服务{私有的 $选民;公众的 功能 __构造($选民){$->选民=$选民;}公众的 功能 canAccess(可以访问)($资源){foreach公司($->选民 作为 $选民) {如果(真的===$选民->canAccess(可以访问)($资源)) {返回 真的;}}返回 ;}}$容器=新的 集装箱();$容器['投票人1']=fn($c(c))=>新的 SomeVoter公司();$容器['投票人2']=fn($c(c))=>新的 其他选民($c(c)[“身份验证”]);$容器[“身份验证”]=fn($c(c))=>新的 授权服务(新的 服务迭代器($c(c),阵列('投票人1',“投票人2”));