mouf / prefixer-container
本包包含一个非常简约的依赖注入容器,作为目标容器的前置代理。其目标是给目标容器中的所有实例命名添加前缀。
Requires
Requires (Dev)
- acclimate/container: ~1.0
- mouf/picotainer: ~1.0
- phpunit/phpunit: ~3.7
- satooshi/php-coveralls: dev-master
This package is auto-updated.
Last update: 2024-09-15 05:28:49 UTC
README
本包包含一个非常简约的依赖注入容器,可用于将容器中的所有标识符添加前缀。Prefixer-container 与 container-interop 兼容,并旨在与其他容器一起使用。Prefix-container 本身不存储任何条目。它只能用于包装现有容器。
您可以使用 PrefixerContainer
将容器的所有标识符放入一个 命名空间 中。
安装
在您的项目中使用 PrefixerContainer
之前,将其添加到您的 composer.json
文件中
$ ./composer.phar require mouf/prefixer-container ~1.0
用法
假设您有两个并存的容器,并且一个组合容器(我们将它称为“根容器”)正在将它们连接起来。现在,这两个容器都声明了一个名为“dbConnection”的相同实例。
如果您想通过根容器访问这两个实例,您会遇到一个问题,因为您有命名冲突。当然,您可以重命名其中一个实例,但如果容器是由第三方库提供的,这可能不可行。
所以您需要做的就是重命名其中一个容器的实例,以消除冲突。这正是 PrefixerContainer
发挥作用的地方。
通过将容器包装在 PrefixerContainer
中,您可以更改实例的名称,使其对外部世界可见。
以下是一个演示上述代码的示例代码
use Mouf\PrefixerContainer\PrefixerContainer; use Acclimate\Container\CompositeContainer; use Interop\Container\ContainerInterface; use Mouf\Picotainer\Picotainer; $rootContainer = new CompositeContainer(); // We use Picotainer, a minimalistic container for this demo. $containerA = new Picotainer([ "dbConnection" => function () { return new DbConnection(...); }, ]); $containerB = new Picotainer([ "dbConnection" => function () { return new OtherDbConnection(...); }, ]); $rootContainer->addContainer(new PrefixerContainer($containerA, 'A.'))); $rootContainer->addContainer(new PrefixerContainer($containerB, 'B.'))); // Get 'dbConnection' from container A: $dbConnectionA = $rootContainer->get('A.dbConnection'); // Get 'dbConnection' from container B: $dbConnectionB = $rootContainer->get('B.dbConnection'); // This will throw a NotFoundException: $willFail = $rootContainer->get('dbConnection');
与委托查找容器协同工作
如果您正在包装的容器实现了 委托查找功能(它应该实现!),您将面临另一个问题。
当您使用委托查找功能时,依赖项将从根容器获取。现在,由于 PrefixerContainer
,依赖项的名称已更改!
想象一下有一个使用 dbConnection
的服务的容器
如果我们把这个容器包装在一个 PrefixerContainer
中?如果我们查询 A.myService
条目(1),容器会将查找 dbConnection
条目的任务委托给 rootContainer。现在,这是一个问题,因为它应该查询 A.dbConnection
条目。
为了解决这个问题,prefixer-container 提供了一个 DelegateLookupUnprefixerContainer
类。这是一个您将用来包装委托查找容器的包装器。当包装器的 get
方法被调用时,它将首先尝试获取带有前缀的实例,如果失败,则尝试获取不带前缀的实例。
如果我们查询 A.myService
条目(1),容器会将查找 dbConnection
条目的任务委托给 rootContainer(2)。这首先通过 DelegateLookupUnprefixerContainer
进行,它将添加 "A." 前缀(3)。查找再次通过根容器进行,然后是 prefixer 容器,它删除 "A.",最后解决依赖项 dbConnection
。 任务完成!
以下是一个演示上述代码的示例代码
use Mouf\PrefixerContainer\PrefixerContainer; use Acclimate\Container\CompositeContainer; use Interop\Container\ContainerInterface; use Mouf\Picotainer\Picotainer; $prefix = "A."; $rootContainer = new CompositeContainer(); // We use Picotainer, a minimalistic container for this demo. $container = new Picotainer([ "dbConnection" => function () { return new DbConnection(...); }, // The myService service requires the 'dbConnection' "myService" => function (ContainerInterface $c) { return new MyService($c->get('dbConnection')); }, ], new DelegateLookupUnprefixerContainer($rootContainer, $prefix)); // In the root container, we add a prefixed version of the container $rootContainer->addContainer(new PrefixerContainer($container, $prefix)); $service = $rootContainer->get('myService');
为什么需要这个包?
本包是长期努力的一部分,旨在实现DI容器之间的互操作性。目标是确保多个容器可以通过共享条目进行通信(一个容器可能使用另一个容器的条目等)。