brightnucleus / injector
Auryn 依赖注入器的配置驱动扩展。
Requires
- brightnucleus/config: >=0.4.7
- brightnucleus/exceptions: >=0.2
- ocramius/proxy-manager: ~2.0
Requires (Dev)
README
基于Auryn的配置驱动依赖注入器。
这是一个配置驱动的依赖注入器,允许通过 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
查找三个配置键: standardAliases
、sharedAliases
和 configFiles
。
注入器通过允许您将别名映射到实现来工作。别名是您想要能够实例化的特定名称。别名可以是类、抽象类、接口或任意字符串。您可以将每个别名映射到注入器应该实例化的具体实现。
这使得您可以通过构造函数注入将类仅依赖于接口,并通过注入器配置文件选择要使用的特定实现。
例如,想象以下类
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。