scruwi/container

PSR-11 容器实现

v0.1.1 2021-09-27 18:49 UTC

This package is auto-updated.

Last update: 2024-09-06 00:32:15 UTC


README

SWUbanner Latest Stable Version Total Downloads License PHP Version Require codecov

这是我自己的PSR-11容器接口实现。

安装

composer require scruwi/container

初始化

$container = new Container([
    new ClassResolver(['App\\Namespace1', 'App\\Namespace2']),
    new ParameterResolver(['param1' => true, 'param2' => 'string']),
    new DefinitionResolver([Definition1:class, Definition2:class]),
]);

解析器

如果需要,你可以在项目中实现自己的解析器。查看 Interfaces 命名空间。

ClassResolver

只有定义的命名空间中的类可以进行自动注入。

ParameterResolver

典型用法

$rootParameters = ['param1' => true, 'param2' => 'string'];
$classSpecificParameters = [SpecificClass::class => ['param1' => false]];
$resolver = ParameterResolver($rootParameters, $classSpecificParameters);

预期行为

class SomeClass
{
    public function __construct(bool $param1) { /* $param1 === true */ }
}
class SpecificClass
{
    public function __construct(bool $param1) { /* $param1 === false */ }
}

具有默认值的参数不必由配置解析

class SpecificClass
{
    public function __construct(bool $param0 = 'default') { /* $param0 === 'default' */ }
}

你可以创建一个特定的解析器并按自己的方式使用它。只需实现 ParameterResolverInterface 并在容器构造时指定它。

DefinitionResolver

将定义附加到容器。

定义,它不过是一个以特定方式创建对象的工厂。有一个特定的 ReflectionClassDefinition 通过反射构造类。所有自动注入的类都使用这个工厂来创建它们的对象。

你应该在你的项目中创建尽可能多的定义,并在容器构造时指定它们,或者稍后通过 $container->addDefinition() 方法附加它们。任何定义都必须实现 DefinitionInterface

典型的定义类如下所示

class ExampleDefinition implements DefinitionInterface
{
    public static function getId(): string
    {
        return ExampleClass::class;
    }

    public function __invoke(Container $container, ParameterResolver $resolver, BuildContext $context): object
    {
        return new ExampleClass();
    }
}

你可以从 ParameterResolver 获取一些默认参数

    public function __invoke(Container $container, ParameterResolver $resolver, BuildContext $context): object
    {
        $param1 = $resolver->resolve('param1', ExampleClass::class);
        return new ExampleClass($param1);
    }

你还可以找出它是从哪个上下文调用的。这可能在自动注入接口时很有用

class InterfaceDefinition implements DefinitionInterface
{
    public function getId(): string
    {
        return SomeInterface::class;
    }

    public function __invoke(Container $container, ParameterResolver $resolver, BuildContext $context): object
    {
        if ($context->getTargetClass() === ClassWithInterfaceDependency::class) {
            return new SomeClassImplementsInterface2();
        }

        return new SomeClassImplementsInterface1();
    }
}

异常

  • NotFoundExceptionInterface - 对于未知条目
  • ContainerExceptionInterface - 对于容器中的所有通用异常
  • CircularReferencesException - 容器中存在循环引用时有一个特殊的异常