mouf / prefixer-container

本包包含一个非常简约的依赖注入容器,作为目标容器的前置代理。其目标是给目标容器中的所有实例命名添加前缀。

1.0.x-dev 2015-02-01 14:43 UTC

This package is auto-updated.

Last update: 2024-09-15 05:28:49 UTC


README

Latest Stable Version Latest Unstable Version License Scrutinizer Code Quality SensioLabsInsight Build Status Coverage Status

本包包含一个非常简约的依赖注入容器,可用于将容器中的所有标识符添加前缀。Prefixer-container 与 container-interop 兼容,并旨在与其他容器一起使用。Prefix-container 本身不存储任何条目。它只能用于包装现有容器。

您可以使用 PrefixerContainer 将容器的所有标识符放入一个 命名空间 中。

安装

在您的项目中使用 PrefixerContainer 之前,将其添加到您的 composer.json 文件中

$ ./composer.phar require mouf/prefixer-container ~1.0

用法

假设您有两个并存的容器,并且一个组合容器(我们将它称为“根容器”)正在将它们连接起来。现在,这两个容器都声明了一个名为“dbConnection”的相同实例。

如果您想通过根容器访问这两个实例,您会遇到一个问题,因为您有命名冲突。当然,您可以重命名其中一个实例,但如果容器是由第三方库提供的,这可能不可行。

The issue

所以您需要做的就是重命名其中一个容器的实例,以消除冲突。这正是 PrefixerContainer 发挥作用的地方。

Solution 1

通过将容器包装在 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 的服务的容器

A container with a dependency

如果我们把这个容器包装在一个 PrefixerContainer 中?如果我们查询 A.myService 条目(1),容器会将查找 dbConnection 条目的任务委托给 rootContainer。现在,这是一个问题,因为它应该查询 A.dbConnection 条目。

Delegate lookup issue

为了解决这个问题,prefixer-container 提供了一个 DelegateLookupUnprefixerContainer 类。这是一个您将用来包装委托查找容器的包装器。当包装器的 get 方法被调用时,它将首先尝试获取带有前缀的实例,如果失败,则尝试获取不带前缀的实例。

Delegate lookup solved

如果我们查询 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容器之间的互操作性。目标是确保多个容器可以通过共享条目进行通信(一个容器可能使用另一个容器的条目等)