avris / container
具有自动装配功能的依赖注入容器
Requires
- avris/bag: ^4.0
- psr/container: ^1.0
- symfony/finder: ^3.0|^4.0
Requires (Dev)
- phpunit/phpunit: ^6.5
- squizlabs/php_codesniffer: ^3.2
- symfony/var-dumper: ^4.0
This package is not auto-updated.
Last update: 2024-09-20 02:59:22 UTC
README
具有自动装配功能的依赖注入容器
安装
composer require avris/container
使用
基础
容器解决定义服务之间的依赖关系,以简化开发过程,避免代码重复,促进互操作性,并提高可维护性和可测试性。见:[依赖注入模式](https://en.wikipedia.org/wiki/Dependency_injection)。
$parameterProvider = new SimpleParameterProvider(['ROOT_DIR' => __DIR__]);
// parameter provider is optional
$container = new Container($parameterProvider);
$container->set('number', 4);
$container->set(Foo::class, new Foo);
$container->setDefinition(Bar::class, [
'arguments' => [
'$foo' => '@' . Foo::class,
'$dir' => '%ROOT_DIR%/bar',
'$number' => '@number',
'$float' => 69.123,
],
'public' => true,
]);
$container->setDefinition(BarInterface::class, Bar::class); // alias
$container->get('number'); // 4
$container->get(Foo::class); // new Foo
$container->get(BarInterface::class); // new Bar(new Foo, __DIR__ . '/bar', 4, 69.123)
$container->getParameter('ROOT_DIR'); // __DIR__
选项
class
-- 服务的类,如果没有提供,将默认为服务名称。如果给定的类实现了Resolver
接口,它将被实例化,并且执行其resolve
方法以提供要放入容器中的实际值。arguments
-- 构造函数参数。calls
-- 在构建服务后立即执行的方法调用(setter 注入等)'calls' => [ ['setLogger', ['@logger']], ['registerListener', ['@listenerA']], ['registerListener', ['@listenerB']], ],
tags
-- 一个字符串数组,有助于将类似的服务分组在一起;带标签的服务可以用#tagName
注入$container->setDefinition(HandlerA::class, ['tags' => 'handler']); $container->setDefinition(HandlerB::class, ['tags' => 'handler']); $container->setDefinition(HandlerC::class, ['tags' => 'handler']); $container->setDefinition(Manager::class, ['arguments' => ['$handlers' => '#handler']]);
factory
-- 确定每次get
是否创建新的服务(true
),或者是否应重用单个服务(false
,默认)。resolve
-- 不使用class
+arguments
构建服务,您可以使用resolve
定义其创建方式$container->setDefinition('foo', ['resolve' => 4]); // 4 $container->setDefinition('language', ['resolve' => '@Request.locale.language']); // $container->get('Request')->getLocale()->getLanguage()
public
-- 确定服务是否可以通过get
直接访问,或者它是否只能注入到其他服务中。
ContainerCompiler:自动装配和自动配置
通常很明显,哪个服务应该注入到另一个服务中。例如,当您的服务有一个构造函数参数 Psr\Cache\CacheItemPoolInterface $cache
,并且容器中确实有一个名为 Psr\Cache\CacheItemPoolInterface
的服务时,则明确写出 ['arguments' => ['$cache' => '@Psr\Cache\CacheItemPoolInterface']
是多余的。您始终可以手动指定依赖项,然后自动装配不会覆盖它们。
自动装配不是魔法 -- 它只是遵循简单的规则来确定,应该将哪个服务注入到构造函数中
- 如果参数是一个在容器中定义的类,则使用此服务,
- 如果参数是一个在容器中未定义的类,则尝试自动装配该类并从它创建一个私有服务,
- 如果参数是数组且其名称以
s
结尾(例如array $helpers
),则注入具有特定标签(#helper
)的服务数组。 - 如果参数是
Bag
类型,则通过其名称注入配置值(例如Bag $localisation
->@config.localisation
), - 如果其名称以
env
开头,则注入一个参数:(例如string $envCacheDir
->%CACHE_DIR%
) - 如果上述任何一项都不成立,但存在默认值,则直接使用该默认值,
- 如果上述任何一项都不成立,则抛出异常 -- 此参数应明确定义。
自动配置是使您的生活更简单的一种方法。例如,如果您正在使用 Twig,您可能希望所有扩展 Twig\Extension\AbstractExtension
的代码中的类都自动注册为 twig 扩展。自动配置允许您定义应该添加到它们的默认配置(标签、公共等)。
要使用自动装配和自动配置,运行 ContainerCompiler
$container = new Container;
$services = [
'App\' => [
'dir' => '%MODULE_DIR%/src/',
'exclude' => ['#^Entity/#'],
],
'App\Foo' => [
'arguments' => [
'$bar' => 5,
],
],
'App\Bar' => [
'public' => true,
],
];
$autoconfiguration = [
'Twig\Extension\AbstractExtension' => [
'tags' => ['twigExtension'],
],
];
$definitions = new ContainerCompiler(
$container,
$services,
$autoconfiguration
))->compile();
/** @var ServiceDefinition $definition */
foreach ($definitions as $name => $definition) {
if (!$container->has($name)) {
$container->setDefinition($name, $definition);
}
}
在此示例中,除了(/src/Entity
目录之外),整个 %MODULE_DIR%/src/
都将被扫描以查找 PHP 文件,并且所有找到的类都将作为私有服务自动装配。如果其中一些未使用且未公开,则将从容器中删除。
只要您缓存 compile()
的结果,编译容器对生产环境中的性能没有影响。
服务定位器
服务定位器仅允许对所选名称列表中的服务进行访问,限制了对容器中服务的访问。
$container = new Container();
$container->set('foo', 'abc');
$container->set('bar', 'def');
$container->set('secret', 'XYZ');
$locator = new ServiceLocator($container, ['foo', 'bar']);
$locator->get('foo'); // 'abc'
$locator->get('bar'); // 'def'
$locator->get('secret'); // Exception
ContainerAssistedBuilder
ContainerAssistedBuilder
可用于将多个封装了一组服务定义的 ContainerBuilderExtension
连接在一起,形成一个库。例如,请参阅 Avris Localisator。
Micrus
该容器最初是作为 Micrus 框架 的一部分构建的。
版权
- 作者: Andre Prusinowski (Avris.it)
- 许可: MIT