brightnucleus/injector

Auryn 依赖注入器的配置驱动扩展。

v0.4.3 2018-01-17 09:44 UTC

This package is auto-updated.

Last update: 2024-08-29 04:14:34 UTC


README

基于Auryn的配置驱动依赖注入器。

Latest Stable Version Total Downloads Latest Unstable Version License

这是一个配置驱动的依赖注入器,允许通过 brightnucleus/config 组件轻松注册别名映射。

它包含来自 rdlowrey/auryn 包的大部分代码。

与Auryn相比的显著变化

  • 可以通过配置文件完成注入器配置。
  • 别名区分大小写。
  • 闭包可以接收一个 InjectionChain 对象,该对象允许您迭代实例化层次结构。

目录

需求

BrightNucleus Injector 需要 PHP 7.0+。

安装

使用此组件的最佳方式是通过 Composer

composer require brightnucleus/injector

基本用法

本文档仅处理通过 Config 文件传递映射。基本方法的文档还需要同步。目前,请参阅Auryn README

Bright Nucleus Injector 期望通过其构造函数获取实现 BrightNucleus\Config\ConfigInterface 的对象。您需要传入正确的“子配置”,以便 Injector 在根级别查找键。

Injector 查找三个配置键: standardAliasessharedAliasesconfigFiles

注入器通过允许您将别名映射到实现来工作。别名是您想要能够实例化的特定名称。别名可以是类、抽象类、接口或任意字符串。您可以将每个别名映射到注入器应该实例化的具体实现。

这使得您可以通过构造函数注入将类仅依赖于接口,并通过注入器配置文件选择要使用的特定实现。

例如,想象以下类

class BookReader
{
    /** @var BookInterface */
    protected $book;

    public function __construct(BookInterface $book)
    {
        $this->book = $book;
    }

    public function read()
    {
        echo $this->book->getContents();
    }
}

如果我们现在定义一个别名 'BookInterface' => 'LatestBestseller',我们可以有如下代码

<?php
$bookReader = $injector->make('BookReader');
// This will now echo the result of LatestBestseller::getContents().
$bookReader->read();

标准别名

标准别名是一个表现得像正常类的别名。因此,对于每次新的实例化(使用 Injector::make()),您将获得一个全新的实例。

标准别名通过 Injector::STANDARD_ALIASES 配置键定义

// Format:
//    '<class/interface>' => '<concrete class to instantiate>',
Injector::STANDARD_ALIASES => [
    'BrightNucleus\Config\ConfigInterface' => 'BrightNucleus\Config\Config',
]

共享别名

共享别名是一个表现得像静态变量的别名,这意味着它们在所有实例化之间被重用。因此,对于每次新的实例化(使用 Injector::make()),您将每次都得到完全相同的实例。对象仅在第一次需要时真正实例化,然后该实例被共享。

共享别名通过 Injector::SHARED_ALIASES 配置键定义

// Format:
//    '<class/interface>' => '<concrete class to instantiate>',
Injector::SHARED_ALIASES => [
    'ShortcodeManager' => 'BrightNucleus\Shortcode\ShortcodeManager',
]

参数定义

参数定义允许您让 Injector 知道在您需要注入标量值时要传递给参数的内容。

// Format:
//
// '<alias to provide argument for>' => [
//    '<argument>' => '<callable or scalar that returns the value>',
// ],
Injector::ARGUMENT_DEFINITIONS => [
	'PDO' => [
		'dsn'      => $dsn,
		'username' => $username,
		'passwd'   => $password,
	]
]

默认情况下,您作为定义传递的值被认为是原始值,可以直接使用。如果您想通过 Injector::ARGUMENT_DEFINITIONS 键传递别名,请将其包装在 BrightNucleus\Injector\Injection 类中,如下所示

Injector::ARGUMENT_DEFINITIONS => [
	'config' => [
		'config' => new Injection( 'My\Custom\ConfigClass' ),
	]
]

参数提供者

参数提供者允许您让 Injector 知道在实例化对象时需要传递哪些参数,例如 $config$logger。由于这些参数可能因每个对象而异,我们需要一种方法将它们映射到特定的别名(而不是使用一个全局值)。这是通过将每个别名映射到返回正确类型对象的调用者来实现的。

对于这些,Injector 会为每个创建一个轻量级的代理对象。当它们第一次被引用时,这些代理对象会被实例化并替换为真实对象。

例如,Bright Nucleus 的几乎所有组件都使用配置文件来完成特定项目的工作。

如果您想将别名映射到配置文件的特定子树,可以通过为每个别名提供一个调用者来实现。当 Injector 尝试实例化该特定别名时,它将调用相应的调用者,并希望得到匹配的配置。

// Format:
// '<argument>' => [
//    'interface' => '<interface/class that the argument accepts>',
//    'mappings'  => [
//        '<alias to provide argument for>' => <callable that returns a matching object>,
//    ],
// ],
Injector::ARGUMENT_PROVIDERS => [
    'config' => [
        'interface' => ConfigInterface::class,
        'mappings'  => [
            ShortcodeManager::class => function ($alias, $interface) {
                return ConfigFactory::createSubConfig(
                    __DIR__ . '/config/defaults.php',
                    $alias
                );
            },
        ],
    ],
]

委托

委托允许您让 Injector 将给定别名的实例化委托给提供的工厂。工厂可以是任何返回与别名匹配类型对象的调用者。

如果您需要操作注入链,例如找出当前需要实例化依赖项的对象,请在您的工厂调用者中添加一个 BrightNucleus\Injector\InjectionChain $injectionChain 参数。您将能够查询传入的注入链。要查询注入链,请将您要获取的索引传递给 InjectionChain::getByIndex($index)。如果您提供一个负索引,您将从队列末尾开始倒数获取第 n 个元素。

例如,考虑一个具有构造函数 __construct( ExampleDependency $dependency )ExampleClass。注入链将是以下(在 namespace Example\Namespace 中)

[0] => 'Example\Namespace\ExampleClass'
[1] => 'Example\Namespace\ExampleDependency'

因此,在下面的示例中,我们使用 getByIndex(-2) 来从注入列表中获取第二个到最后一个元素。

// Format:
//    '<alias>' => <callable to use as factory>
Injector::DELEGATIONS => [
	'Example\Namespace\ExampleDependency' => function ( InjectionChain $injectionChain ) {
		$parent = $injectionChain->getByIndex(-2);
		$factory = new \Example\Namespace\ExampleFactory();
		return $factory->createFor( $parent );
	},
]

准备

准备允许您让 Injector 定义在对象实际使用之前需要进行的额外准备步骤。

调用者将接收两个参数,要准备的对象以及注入器的引用。

// Format:
//    '<alias>' => <callable to execute after instantiation>
Injector::PREPARATIONS => [
	'PDO' => function ( $instance, $injector ) {
		/** @var $instance PDO */
		$instance->setAttribute(
			PDO::ATTR_DEFAULT_FETCH_MODE,
			PDO::FETCH_OBJ
		);
	},
]

注册额外映射

您可以通过简单地将额外的配置传递给 Injector::registerMappings() 方法在任何时间注册额外的映射。它采用与构造函数相同的格式。

$config = ConfigFactory::create([
    Injector::STANDARD_ALIASES => [
        'ExampleInterface' => 'ConcreteExample'
    ]
]);
$injector->registerMappings($config);
// Here, `$object` will be an instance of `ConcreteExample`.
$object = $injector->make('ExampleInterface');

注意:对于如此简单的示例,创建配置文件当然是过度的。您也可以使用基本的 Auryn 别名功能 并使用 Injector::alias() 添加额外的别名。请参阅 Auryn 文档 了解有关手动配置注入器的不同方法。

贡献

所有反馈/错误报告/拉取请求都欢迎。

此包使用 PHP Composter PHPCS PSR-2 包来检查提交文件是否符合 PSR-2 编码风格指南。如果您有有效理由跳过此检查,请将 --no-verify 选项添加到您的提交命令中

git commit --no-verify

许可证

此代码在 MIT 许可证下发布。

有关完整的版权和许可信息,请查看与此源代码一起分发的 LICENSE 文件。

本代码的大部分最初来源于 rdlowrey/auryn 项目。

Auryn 原始代码的版权为(c)2013-2014 Daniel Lowrey,Levi Morrison,Dan Ackroyd。

Auryn 贡献者列表