jitesoft /container
PSR-11 容器,具有构造器注入。
Requires
- php: >=8.1
- jitesoft/exceptions: ^2.4
- psr/container: ^2
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.7
This package is auto-updated.
Last update: 2024-09-15 20:05:22 UTC
README
容器
绑定
容器将一个键绑定到一个值,该值可以是任何类型或类名。
如果它是一个对象、原始类型或任何类型的实例,它将实例存储为静态对象,即在每次 get
调用时返回相同的对象。而如果传递了一个类名,容器将尝试在每次 get
调用时创建该类的实例。如果无法创建实例,则抛出 NotFoundException 或 ContainerException。
绑定可以通过在构造函数中传递关联数组或使用 set
方法来完成。要重新绑定,可以使用接受键和值的 rebind
方法。
容器实现了 PSR-11 容器接口。此外,容器实现了 ArrayAccess
接口,可以通过数组索引语法进行获取,例如:$container[Interface::class]
。
使用方法
容器实现了以下接口
interface ContainerInterface { public function get($abstract): mixed; public function has($abstract): bool; } interface ArrayAccess { public function offsetExists($offset); public function offsetGet($offset); public function offsetSet($offset, $value); public function offsetUnset($offset); }
ArrayAccess
接口允许通过数组索引语法获取、设置和取消设置绑定
$c['Abstract'] = 'Concrete'; echo $c['Abstract']; // 'Concrete' unset($c['Abstract'];
此外,该类还实现了以下公共方法
class Container { public function __construct(?array $bindings); public function clear(); public function set(string $abstract, mixed $concrete, ?bool $singleton = false): bool; public function rebind(string $abstract, mixed $concrete, ?bool $singleton = false): void; public function unset(string $abstract): void; public function singleton(string $abstract, mixed $concrete): void; }
类的构造函数接受一个可选的绑定数组。期望的数组应该是一个关联数组,其中包含抽象类作为键,具体实现作为值。如果需要,具体实现可以是另一个包含 class
或 func
键的关联数组,这些键包含要解析到的/与的类或可调用的函数,以及一个包含布尔值的 singleton
键。
如果 singleton 键为 true,容器将始终创建解析值的单个实例,或者只运行解析函数一次。
示例
$container = new Container([ // With objects: InterfaceA::class => $objectInheritingInterfaceA, InterfaceB::class => [ 'class' => $objectInheritingInterfaceB, 'singleton' => true ], // With classes: InterfaceA::class => ClassA::class, InterfaceB::class => [ 'class' => ClassB::class, 'singleton' => true ], // Or with functions: InterfaceA::class => static fn (InterfaceB $ib) => new ClassA($ib), InterfaceB::class => [ 'class' => static function(InterfaceC $c) { return new ClassB($c); }, 'singleton' => true ], ]); $container->get(InterfaceA::class); // Will be a new object of the ClassA class. $container->get(InterfaceB::class); // On first call, it will be resolved to a ClassB class. $container->get(InterfaceB::class); // On all other calls, the object will be the same as the first call.
除了数组类型单例绑定之外,接口还可以使用 singleton
方法创建单例绑定。
可以使用 $container->rebind($a, $c, $singleton);
方法在运行时重新绑定。
这将取消之前的绑定并创建一个新的绑定。
要删除所有当前绑定,可以使用 $container->clear();
方法,这将清空内部条目列表。请注意,这不会清除存储在您的类中的当前解析对象实例,而是从容器中删除所有条目。
类中实现的除 has
和 clear
方法之外的所有方法在出错时都将抛出异常。
以下两个异常被使用
Jitesoft\Exceptions\Psr\Container\ContainerException implements ContainerExceptionInterface;
Jitesoft\Exceptions\Psr\Container\NotFoundException implements NotFoundExceptionInterface;
因此,在检查异常时,可以使用底层的 JitesoftException
类、特定类或接口。
但是请注意,NotFoundException
继承自 ContainerException
,因此,在两者都可以返回且您想要捕获特定异常的情况下,请先捕获 NotFoundException
,然后捕获 ContainerException
。
依赖注入
当容器能够做到时,它将在解析对象时将依赖项注入到构造函数中。
但在它能够这样做之前有一些要求
- 参数需要类型提示。
- 参数需要在容器中可解析,或者可以在没有构造函数的情况下创建。
如果容器无法解析参数,它将抛出异常,但根据上述两个要求,这种情况不应该发生。
class ClassA {} class ClassB { __constructor(ClassA $b) { } } $container->set(ClassB::class, ClassB::class); $container->get(ClassB::class); // Will throw a ContainerException due to class A not being bound. $container->set(ClassA::class, ClassA::class); $container->get(ClassB::class); // Will not throw any exception. ClassA is resolved and pushed into the constructor of ClassB.
不仅仅是类
容器不仅解析绑定,还可以用来存储其他值。
如果传递的具体不是类名,它将使用它作为单个值,而不是解析。因此,传递字符串或数字作为具体值将使 get
方法返回该值。
$container->set('Something', 123); $container->get('Something'); // 123
许可证
MIT