maiorano84 / league-container-config
league/container 的简单构建器
Requires
- php: ^7.4
- league/container: ^3.3
Requires (Dev)
- phpunit/phpunit: ^9.1
- vimeo/psalm: ^3.11
This package is auto-updated.
Last update: 2024-09-11 15:29:08 UTC
README
一个简单的 Builder 模式,用于从格式化的数组中创建完整的 league/container 实例。
要求
League Container Builder 需要 PHP 7.4 或更高版本。
Composer
您可以通过运行以下命令将此包作为 Composer 依赖项安装
composer require maiorano84/league-container-config
如果您想使用最新不稳定版本,可以运行
composer require maiorano84/league-container-config:dev-master
用法
这是一个针对 The PHP League's Container 包的小型附加组件,它允许您在应用程序中传递配置对象并接收完整的 Container 实例。
有 4 个可用的构建器可供使用
- ContainerBuilder - 主要构建器,用于实例化其构建器依赖项以及构造 Container 实例
- DefinitionBuilder - 负责构造 Definition 实例并将其添加到其内部 DefinitionAggregate
- InflectorBuilder - 负责构造 Inflector 实例并将其添加到其内部 InflectorAggregate
- ServiceProviderBuilder - 负责构造 ServiceProvider 实例并将其添加到其内部 ServiceProviderAggregate
所有构建器都实现了 Maiorano\ContainerConfig\BuilderInterface
,它提供了访问简单 build
方法的权限,该方法接受一个配置数组,并返回每个构建器负责构造的对象。
为什么?
如果您需要应用程序的 DI 容器可由用户配置,那么这可能有所帮助。而不是直接传递 Container 实例并让用户去解决如何连接所有内容,您可以选择配置文件(PHP、JSON、XML、YAML 等)来解析,然后一次性构建。
即使您没有计划发布需要这种层次抽象的应用程序,也可以将其用作将逻辑简化为更简洁和更具表达性的结构的方法。
除了这些原因之外,它提供的好处并不比 Container 本身处理的多。
Container 构建器
建议使用 make
工厂方法实例化 Container 构建器
use Maiorano\ContainerConfig\ContainerBuilder;
$builder = ContainerBuilder::make();
从这里,可以使用 build
命令生成 Container 对象
use League\Container\ReflectionContainer;
use Maiorano\ContainerConfig\ContainerBuilder;
$builder = ContainerBuilder::make();
$container = $builder->build([
'definitions' => [
AbstractInterface::class => Concrete::class, // Simple Mapping
'name' => [ // Complete Definition structure
'alias' => AbstractInterface::class,
'concrete' => Concrete::class,
'shared' => true,
'arguments' => [Dependency::class, 'arg2', 'arg3'],
'methods' => ['methodName' => ['arg1', 'arg2']],
'tags' => ['tag1', 'tag2', 'tag3'],
],
],
'serviceProviders' => [
CustomServiceProvider::class,
new UserDefinedServiceProvider,
],
'inflectors' => [
DefinitionAlias::class => 'methodName', // Simple inflector
OtherDefinitionAlias::class => [ // Complete Inflector Structure
'callback' => function($object){ var_dump($object); },
'properties' => ['propery' => 'value'],
'methods' => ['methodName' => ['arg1', 'arg2']],
],
],
'delegates' => [
$anotherContainerObject,
ReflectionContainer::class,
],
]);
在这个示例中,将每个顶级配置块传递给相应的构建器,构建各种聚合并将它们发送到 Container 对象。
Definition 构建器
Definition 构建器只需要一个满足 DefinitionAggregateInterface
的对象。可以使用 Container Definitions 进行批量或逐个构建。
使用 build
批量生成定义
use Maiorano\ContainerConfig\DefinitionBuilder;
use League\Container\Definition\DefinitionAggregate;
$builder = new DefinitionBuilder(new DefinitionAggregate);
$aggregate = $builder->build([
AbstractInterface::class => Concrete::class, // Simple Mapping
'name' => [ // Complete Definition structure
'alias' => AbstractInterface::class,
'concrete' => Concrete::class,
'shared' => true,
'arguments' => [Dependency::class, 'arg2', 'arg3'],
'methods' => ['methodName' => ['arg1', 'arg2']],
'tags' => ['tag1', 'tag2', 'tag3'],
],
]);
在极少数需要使用定义构建器的 buildDefinition
方法的场合,可以按照以下方式逐个构造单个定义
use Maiorano\ContainerConfig\DefinitionBuilder;
use League\Container\Definition\DefinitionAggregate;
$builder = new DefinitionBuilder(new DefinitionAggregate);
$definition = $builder->buildDefinition('name', [
'alias' => AbstractInterface::class,
'concrete' => Concrete::class,
'shared' => true,
'arguments' => [Dependency::class, 'arg2', 'arg3'],
'methods' => ['methodName' => ['arg1', 'arg2']],
'tags' => ['tag1', 'tag2', 'tag3'],
]);
定义别名
尽管始终建议使用数组键或 'alias' 映射来定义别名,但 Definition 构建器也会尽力为您解析别名,以防未提供。
定义别名按以下顺序解析
- 配置值是否包含内嵌的 'alias' 键?如果是,则使用它。
- 配置键是否为非数字?如果是,则使用它。
- 提供的具体值是否表示有效类或接口的字符串?如果是,则使用它。
- 提供的具体值是否为一个对象?如果是,则使用
get_class
生成别名。 - 如果上述所有条件都不成立,则使用提供的键作为别名。
在不常见的情况下,如果提供的具体值实现了League\Container\Definition\DefinitionInterface
,则构建器将假定用户意图提供自己的定义,并将绕过自己的构建过程,转而使用用户的实现。
在这种情况下,别名解析方式如下
- 配置值是否包含内嵌的 'alias' 键?如果是,则使用它。
- 配置键是否为非数字?如果是,则使用它。
- 如果上述所有条件都不成立,则使用现有的定义别名。
服务提供者构建器
服务提供者构建器只需要一个满足ServiceProviderAggregateInterface
的对象。服务提供者可以批量或单个构建。
使用build
批量生成服务提供者
use Maiorano\ContainerConfig\ServiceProviderBuilder;
use League\Container\ServiceProvider\ServiceProviderAggregate;
$builder = new ServiceProviderBuilder(new ServiceProviderAggregate);
$aggregate = $builder->build([
CustomServiceProvider::class,
new UserDefinedServiceProvider,
]);
在不常见的情况下,如果您需要服务提供者构建器自己的buildServiceProvider
方法,可以以下方式将单个服务提供者添加到聚合中
use Maiorano\ContainerConfig\ServiceProviderBuilder;
use League\Container\ServiceProvider\ServiceProviderAggregate;
$builder = new ServiceProviderBuilder(new ServiceProviderAggregate);
$aggregate = $builder->buildServiceProvider(CustomServiceProvider::class);
重要提示
即使在使用buildServiceProvider
方法的情况下,对聚合的add
方法的底层调用也将返回ServiceProviderAggregate
,而不是服务提供者本身。
Inflector构建器
Inflector构建器只需要一个满足InflectorAggregateInterface
的对象。Inflectors可以批量或单个构建。
使用build
批量生成Inflectors
use Maiorano\ContainerConfig\InflectorBuilder;
use League\Container\Inflector\InflectorAggregate;
$builder = new InflectorBuilder(new InflectorAggregate);
$aggregate = $builder->build([
DefinitionAlias::class => 'methodName', // Simple inflector
OtherDefinitionAlias::class => [ // Complete Inflector Structure
'properties' => ['propery' => 'value'],
'methods' => ['methodName' => ['arg1', 'arg2']],
],
]);
在不常见的情况下,如果您需要Inflector构建器自己的buildInflector
方法,可以以下方式将单个Inflectors添加到聚合中
use Maiorano\ContainerConfig\InflectorBuilder;
use League\Container\Inflector\InflectorAggregate;
$builder = new InflectorBuilder(new InflectorAggregate);
$inflector = $builder->buildInflector(OtherDefinitionAlias::class, [
'callback' => function($object){ var_dump($object); },
'properties' => ['propery' => 'value'],
'methods' => ['methodName' => ['arg1', 'arg2']],
]);
其他注意事项
构建模式的目的在于构建新的对象。虽然当然可以使用现有的聚合并通过Builder调用对其进行修改,但这并不推荐,并且可能被视为对构建器的一般误用。
相反,如果您需要精确控制容器的各个部分,则建议在初始构建完成后直接与结果容器或其聚合进行交互。