tsufeki/hmcontainer

依赖注入容器

0.3.5 2019-12-03 19:21 UTC

README

HMContainer 是一个 PHP 的依赖注入容器。

安装

使用 Composer

$ composer require tsufeki/hmcontainer

使用方法

创建容器

use Tsufeki\HmContainer\Container;

$c = new Container();

添加值(常量参数)

$c->setValue("key", 42);

检索它(HMContainer 实现 PSR-11

$c->has("key"); // true
$c->get("key"); // 42
$c->get("non-existent-key"); // throws NotFoundException
$c->getOrDefault("non-existent-key", 5); // 5

容器在第一次 get()freeze() 调用期间被冻结,之后无法添加新项目。

定义对象

向容器中添加项目有两种方式:便捷方法 Container::setValue()::setClass() 等,或者通过创建自己的 Definition 对象并调用 Container::set()。即这两行是等价的

use Tsufeki\HmContainer\Definition\Value;

$c->setValue("key", 42);
$c->set("key", new Value(42));

多值键

添加多个要作为数组检索的项目

$c->setValue("primes", 2, true);
$c->setValue("primes", 3, true);
$c->setValue("primes", 5, true);
$c->isMulti("primes"); // true
$c->get("primes"); // [2, 3, 5]

类实例化和自动装配

添加将在第一次 get() 时实例化的类

$c->setClass("aobject", AClass::class, false, ["dep1", "dep2"]);
$c->get("aobject"); // returns new AClass($c->get("dep1"), $c->get("dep2"))
$c->get("aobject"); // returns the same instance as above

如果使用类名作为 DI 键,则可以自动推断(自动装配)依赖关系

class BClass { }

class CClass {
  public function __construct(BClass $b) { }
}

$c->setClass(BClass::class);
$c->setClass(CClass::class);
$c->get(CClass::class); // correctly contructed CClass object

自动装配键从参数类型提示、@param 标签类型或特殊的 @Inject 标签中猜测

class DClass {
  /**
   * @param CClass $c
   * @param $d @Inject("dkey")
   */
  public function __construct(BClass $b, $c, $d) { }
}

也支持多项目

class Aggregator {
  /**
   * @param SomeInterface[] $impls
   */
  public function __construct(array $impls) { }
}

$c->setClass(SomeInterface::class, ConcreteImplementation1::class, true);
$c->setClass(SomeInterface::class, ConcreteImplementation2::class, true);
$c->setClass(Aggregator::class);
$c->get(Aggregator::class);

将参数标记为 @Optional 以在依赖关系无法找到时注入 null

class Maybe {
  /**
   * @param $dep @Optional
   */
  public function __construct(Dep $dep = null) { }
}

通过在依赖数组中放置一些 null,可以手动依赖和自动装配的混合

$c->setClass(DClass::class, null, false, [null, "dep2"]);

也支持使用 Definition 作为依赖关系

use Tsufeki\HmContainer\Definition\Reference;

$c->setClass(DClass::class, null, false, [null, new Reference("dep2")]);

别名

添加到其他键的别名

$c->setAlias("alias", "target");
$c->get("alias"); // same as $c->get("target")

延迟项目

添加延迟项目,它将返回无参数的可调用对象

$c->setLazy('lazy', new Value(42));
$c->get('lazy'); // a callable $f such that $f() === 42

自定义定义

您可以通过实现 Definition 接口并使用 set() 方法来添加自己的自定义实例化器

$myFactory = new MyFactory();
$c->set("mykey", $myFactory);

序列化

容器可以序列化和反序列化以进行缓存,使用标准的 PHP serialize()unserialize(),但仅当您使用可序列化的工厂时。

许可协议

MIT - 查看 LICENCE