bluepsyduck / zend-autowire-factory
Requires
- php: >=7.1
- zendframework/zend-servicemanager: ^3.0
Requires (Dev)
- bluepsyduck/test-helper: ^1.0
- mikey179/vfsstream: ^1.6
- phpstan/phpstan: ^0.11
- phpstan/phpstan-phpunit: ^0.11
- phpstan/phpstan-strict-rules: ^0.11
- phpunit/phpunit: ^7.0 || ^8.0
- rregeer/phpunit-coverage-check: ^0.1
- squizlabs/php_codesniffer: ^3.4
- zendframework/zend-config-aggregator: ^1.1
This package is auto-updated.
Last update: 2020-11-11 09:56:35 UTC
README
已弃用:请使用包 bluepsyduck/laminas-autowire-factory。
bluepsyduck/laminas-autowire-factory 包具有与该包相同的功能,唯一的区别是命名空间。除了导入之外,无需任何更改。
此库提供了一些帮助将服务类自动装配的工厂,以减少实际工厂的使用。
AutoWireFactory
AutoWireFactory
使用实际服务类的构造函数进行反射,以确定如何解析依赖关系并创建实际服务。该工厂采用 Symfony的自动装配方法,特别是处理相同类型的多个实现。
解析策略
根据参数的类型提示,工厂使用以下策略来解析构造函数的参数。容器中可用的第一个别名将被用来解析依赖关系。如果没有可用的别名,将引发异常。
每个参数都是独立解析的,因此它们可以以任何方式组合。
具有类类型提示的参数
示例: __construct(FancyClass $fancy)
如果参数有类名作为类型提示,则在容器中检查以下别名
FancyClass $fancy
:类名和参数名的组合。这允许有多个相同接口的实现,如Symphony文档所述。FancyClass
:将类注册到容器中的“默认”情况。$fancy
:仅使用参数名作为后备。
将使用容器提供的第一个别名。
具有标量类型提示的参数
示例: __construct(array $fancyConfig)
如果参数使用标量类型提示,例如将配置值拉入服务,则检查以下别名
array $fancyConfig
:类型和参数名的组合,与类类型提示相同。$fancyConfig
:仅使用参数名作为后备。
请注意,类型本身(例如,array
)不作为别名使用。
没有类型提示的参数
示例:__construct($fancyParameter)
由于信息缺失,在这种情况下只能检查一个别名。
$fancyParameter
:回退是唯一可能的别名。
将AutoWireFactory作为AbstractFactory
除了使用FactoryInterface
,将AutoWireFactory
作为显式工厂在容器配置中,它还实现了AbstractFactoryInterface
:如果您将此工厂作为抽象工厂添加,它将尝试自动连接所有内容。这将使配置容器主要变得过时,除非使用标量值或多个实现(其中参数名称是容器别名的部分)的参数。
缓存
AutoWireFactory
使用反射来解决依赖项。为了加快速度,工厂在文件系统中建立缓存以避免在每个脚本调用中使用反射。要启用缓存,请添加以下行,例如在config/container.php
文件中:
\BluePsyduck\ZendAutoWireFactory\AutoWireFactory::setCacheFile('data/cache/autowire-factory.cache.php');
ConfigReaderFactory
为了进一步使自定义工厂过时,ConfigReaderFactory
能够将应用程序配置的值提供给容器,例如与自动连接一起使用。
用法
ConfigReaderFactory
需要将应用程序配置作为数组添加到容器中。如果配置的别名与默认的“config”不同,请调用ConfigReaderFactory::setConfigAlias('yourAlias')
来设置别名。
然后,使用readConfig(string ...$keys)
函数(或new ConfigReaderFactory(string ...$keys)
)来读取容器的配置值,其中$keys
是要在配置中到达所需值的数组键。请注意,如果键未设置,工厂将触发异常。
AliasArrayInjectorFactory
AliasArrayInjectorFactory
从配置中读取别名数组(使用ConfigReaderFactory
),并为这些别名创建所有实例,然后返回以注入到其他服务中。所有别名都必须为容器所知。
要在容器配置中使用此工厂,只需调用injectAliasArray(string ...$configKeys)
(或new AliasArrayInjectorFactory(string ...$configKeys)
)即可。
示例
以下示例应显示如何使用AutoWireFactory
和ConfigReaderFactory
来自动连接服务类。
假设我们有以下应用程序配置,我们希望从中获取值
[ 'fancy-service' => [ 'fancy-property' => 'Hello World!', 'fancy-adapters' => [ FancyAdapterAlpha::class, FancyAdapterOmega::class, ], ], ]
我们希望自动连接以下服务类
class FancyService { public function __construct(FancyComponent $component, string $fancyProperty, array $fancyAdapters) { } } class FancyComponent {} class FancyAdapterAlpha {} class FancyAdapterOmega {}
以下配置可以在不编写任何工厂的情况下用于容器
<?php use BluePsyduck\ZendAutoWireFactory\AutoWireFactory; use Zend\ServiceManager\Factory\InvokableFactory; use function BluePsyduck\ZendAutoWireFactory\injectAliasArray; use function BluePsyduck\ZendAutoWireFactory\readConfig; return [ 'dependencies' => [ 'factories' => [ // Enable auto-wiring for the service itself. FancyService::class => AutoWireFactory::class, // FancyComponent does not need any factory as it does not have a constructor. // Both InvokableFactory and AutoWireFactory are usable here. FancyComponent::class => InvokableFactory::class, FancyAdapterAlpha::class => InvokableFactory::class, FancyAdapterOmega::class => InvokableFactory::class, // Enable the scalar property for auto-wiring into the service. // In this example, the factory would fetch "Hello World!" from the config. 'string $fancyProperty' => readConfig('fancy-service', 'fancy-property'), // Inject an array of other services through their aliases into the service. // In this example, instances of FancyAdapterAlpha and FancyAdapterOmega would be injected. 'array $fancyAdapters' => injectAliasArray('fancy-service', 'fancy-adapters'), ], ], ];
如果使用AutoWireFactory
作为抽象工厂,此配置可以进一步缩短
<?php use BluePsyduck\ZendAutoWireFactory\AutoWireFactory; use function BluePsyduck\ZendAutoWireFactory\injectAliasArray; use function BluePsyduck\ZendAutoWireFactory\readConfig; return [ 'dependencies' => [ 'abstract_factories' => [ // Will auto-wire everything possible to be auto-wired, in our case both FancyService and FancyComponent. AutoWireFactory::class, ], 'factories' => [ // Any aliases using property names cannot be handled by the AutoWireFactory and must still get listed. 'string $fancyProperty' => readConfig('fancy-service', 'fancy-property'), 'array $fancyAdapters' => injectAliasArray('fancy-service', 'fancy-adapters'), ], ], ];
当然,如果自动连接由于更复杂的初始化要求而不可行,始终可以向任何服务添加具体工厂。