edvin / hbcontainer
轻量级容器
v6.1.2
2023-08-09 11:30 UTC
Requires
- php: >=8.0 <9.0
- psr/container: ^1.0|^2.0
Requires (Dev)
- phpstan/phpstan: ^1.4.0
- phpunit/phpunit: ^9.0
This package is auto-updated.
Last update: 2024-09-15 11:48:05 UTC
README
A PSR-11轻量级依赖注入容器,适用于所有类型的项目。支持php 8.0及更高版本。
安装
使用composer
composer require edvin/hbcontainer
解析
HbContainer使用definitions
来定义容器需要解析的条目。容器可以解析任何可以自行构造具有可解析依赖项的类。解析的条目默认存储为弱引用,并可以设置为单例,这将使用正常引用。
获取条目
HbContainer有三种主要方法来获取/调用条目
get
:解析并运行时缓存解析的值以供下一次调用。make
:始终解析并返回一个新实例。call
:解析提供的参数作为要调用的东西,并解析其参数。
HbContainer接受一个包含多个定义的DefinitionSource
,这些定义告诉容器如何解析特定条目。不同类型包括
DefinitionFactory
:一个定义,包含一个闭包以返回其最终状态的项。结果被添加到单例缓存中。辅助函数:\HbLib\Container\factory
DefinitionClass
:一个定义,可以带参数或不带参数构建类。如果定义了任何参数,类永远不会在运行时缓存。辅助函数:\HbLib\Container\resolve
。可以为此定义提供类,如果没有提供,它将假设定义ID(定义数组的索引)是类名。下面是使用示例。DefinitionReference
:一个定义,用于引用另一个定义条目,您可能无法为此定义提供参数。辅助函数:\HbLib\Container\reference
。DefinitionValue
:一个定义,用于返回一些值。该值本身可以是另一个定义。辅助函数:\HbLib\Container\value
。
接口
当依赖于容器时,建议依赖于提供的接口
\Psr\Container\ContainerInteface
:提供get
方法。\HbLib\Container\FactoryInterface
:提供make
方法。\HbLib\Container\InvokerInterface
:提供call
方法。
使用方法
<?php // Helper functions for definitions: use function \HbLib\Container\resolve; use function \HbLib\Container\reference; use function \HbLib\Container\factory; interface MyInterface {} class MyClass implements MyInterface {} class MyClass2 { public $value; function __construct($value) { $this->value = $value; } } class MyClass3 { public $value; function __construct(MyInterface $value) { $this->value = $value; } } class MyClass4 implements MyInterface {} class MyManager { function __construct(string $type) {} } $definitions = array( // Factories: 'session' => factory(function() { return true; }), 'lol' => factory(function() { return false; }), 'hello' => factory(function() { return null; }), MyManager::class => factory(function() { return new MyManager('someType'); }), MyInterface::class => resolve(MyClass::class), // Providing the class to resolve is not required when you want to resolve the ID of the definition itself. MyClass4::class => resolve(), 'differentMyInterface' => factory(function() { return new MyClass(); }), 'myClass2' => resolve(MyClass::class)->parameter('value', 'someValue'), // The ->parameter part is not required as the container can resolve the parameters // but it is here to display that you can tell the container to use another instance. 'myClass3' => resolve(MyClass3::class)->parameter('value', reference('differentMyInterface')), ); // Construct the container. $containerBuilder = new \HbLib\Container\ContainerBuilder($definitions); $containerBuilder->enableComiling(sys_get_temp_dir() . '/CompiledContainer.php'); $container = $containerBuilder->build(); // You can also construct the container like: // $container = new \HbLib\Container\Container(new \HbLib\Container\DefinitionSource($definitions)); // PSR-11 method: $container->get('session'); // => true $container->get('lol'); // => false $container->get('hello'); // => null // PSR-11 $container->has('session'); // => true $container->has('where'); // => false $container->has('hello'); // => true
编译
容器支持将所有解析的定义编译成文件以提高性能。在生产环境中,这种优势在于容器不需要每次都查找所有参数,而是将所有定义及其依赖关系解析到一个文件中。
如何操作
必须在ContainerBuilder上启用编译,并且某些脚本必须调用writeCompiled
在您的Web应用中某处
<?php //... $builder = new \HbLib\Container\ContainerBuilder(new \HbLib\Container\DefinitionSource([ //... ])); $filePath = sys_get_temp_dir() . '/CompiledContainer.php'; $builder->enableCompiling($filePath); // important step if (!is_file($filePath)) { $builder->writeCompiled(); } $container = $builder->build();
我建议在单独的cli命令中执行ContainerBuilder::writeCompiled
调用,以便错误不会影响您的客户端。
<?php // compile_container.php // load build just like you would in web app: $builder = new \HbLib\Container\ContainerBuilder(new \HbLib\Container\DefinitionSource([ //... ])); $filePath = sys_get_temp_dir() . '/CompiledContainer.php'; $builder->enableCompiling($filePath); // important step $builder->writeCompiled();