aeris / zf-di-config
为 ZF2 ServiceManager 提供可配置的依赖注入
Requires
- php: >=5.3.3
- zendframework/zendframework: 2.3.*
Requires (Dev)
- mockery/mockery: ~0.9
- phpunit/phpunit: ~3.7
README
为 ZF2 ServiceManager 提供可配置的依赖注入。
安装
您可以使用 composer 安装 ZfDiConfig
composer require aeris/zf-di-config
然后将模块添加到您的应用程序配置中
// config/application.config.php
return [
'modules' => [
'ZfDiConfig',
// ...
],
// ...
];
基本用法
ZfDiConfig 允许您配置服务,而不是使用服务工厂。例如
// module.config.php return [ 'my_app' => [ 'foo' => [ 'bar' => 'qux' ] ], 'service_manager' => [ // Config for ZfDiConfig 'di' => [ 'SomeService' => '\MyApp\SomeService', 'FooService' => [ 'class' => '\MyApp\FooService', 'args' => ['@SomeService'], 'setters' => [ 'bar' => '%my_app.foo.bar' ] ] ] ] ];
在这个例子中,我们
- 创建了一个名为 "SomeService" 的服务,其实例为
\MyApp\SomeService
- 创建了一个名为 "FooService" 的服务,其实例为
\MyApp\FooService
- 将
SomeService
注入到FooService
作为构造函数参数 - 使用
FooService::setBar()
设置bar
的配置值
与典型的 ZF2 创建服务方法进行比较
// module.config.php return [ 'my_app' => [ 'foo' => [ 'bar' => 'qux' ] ], 'service_manager' => [ 'invokables' => [ 'SomeService' => '\MyApp\SomeService', ] 'factories' =>" [ 'FooService' => '\MyApp\Factory\FooServiceFactory.php' ] ] ]; // MyApp/Factory/FooServiceFactory.php namespace MyApp\Factory; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; class FooServiceFactory implements FactoryInterface { public function createService(ServiceLocatorInterface $serviceLocator) { $someService = $serviceLocator->get('SomeService'); // Inject SomeService into FooService $fooService = new \MyApp\FooService($someService); // Set the a parameter from the module config // onto FooService $config = $serviceLocator->get('config'); $bar = $config['my_app']['foo']['bar']; $fooService->setBar($bar); return $fooService; } }
这种方法可行,但可能变得非常冗长,并且难以一眼看出服务之间的连接方式。
ZfDiConfig 采用不同的方法,允许您配置服务之间的连接方式
插件
ZfDiConfig 使用插件来解决配置引用。提供了一些插件以覆盖基本用法,尽管您也可以轻松添加自己的插件。
大多数插件允许配置的简短或长形式。例如,ServiceResolverPlugin 可以作为 $service
或使用 @
前缀进行引用
[ 'FooService' => [ 'class' => '\MyApp\FooService', 'args' => [ // these two arguments are equivalent '@BarService', [ '$service' => [ 'name' => 'BarService' ] ] ] ] ]
默认插件
默认情况下,ZfDiConfig 使用 $factory
插件来配置服务,因此
[ 'FooService' => '\App\Service\Foo' ]
...等同于...
[ 'FooService' => [ '$factory' => '\App\Service\Foo' ] ]
如果您不想使用 $factory
插件来定义服务,有几个选择。一方面,您可以使用不同的插件,而 DiConfig
将足够智能以识别它。
[ 'FooConfig' => '%my_app.options.foo' // DiConfig won't try to use $factory here ]
您还可以在 zf_di_config
模块配置中覆盖全局默认插件
[ 'zf_di_config' => [ 'default_plugin' => '$myAwesomePlugin', 'plugins' => [...] ] ]
工厂插件
这是配置服务时使用的默认插件。它允许您创建配置的对象实例。您已经在基本用法示例中看到了这个插件的使用方法。
一个有趣的事情是,您实际上可以在其他插件配置中“内联”使用此插件。让我演示一下
[
'FooService' => [
'class' => '\MyApp\FooService',
'args' => [
// Inject a BarService instance "on the fly"
[ $factory' => '\MyApp\BarService' ]
]
]
]
配置引用
FactoryPlugin
可以接受以下配置
简短形式
[ '$factory' => '\MyApp\FooService' ]
非常简短的形式
[
'$factory:\MyApp\FooService'
]
长形式
[ '$factory' => [ // Object class (required) 'class' => '\MyApp\FooService', // services to inject in constructor (optional) 'args' => ['@SomeService'], // Service to inject using setters 'setters' => [ // This will inject 'SomeService' // using the FooService::setBar() method 'bar' => '@SomeService' ] ] ]
服务解析插件
服务解析插件解决对现有服务的引用。
配置引用
简短形式
[ '@NameOfService`, // resolves to $serviceLocator->get('NameOfService') '@NameOfService::foo' // resolves to $serviceLocator->get('NameOfService')->getFoo() ]
长形式
[ '$service' => [ 'name' => 'NameOfService', // optional 'getter' => 'foo' ] ]
配置参数插件
ConfigParamPlugin
允许您访问您应用程序配置中的原始值。
配置引用
简短形式
[ // resolves to $serviceLocator->get('config')['foo']['bar']['faz'] '%foo.bar.faz' ]
长形式
[ '$param' => [ 'path' => 'foo.bar.faz', 'default' => 'qux' ] ]
服务管理器插件
服务管理器插件允许您动态创建服务管理器插件。创建的服务管理器可以使用 ZfDiConfig 进行配置,就像顶级服务管理器一样。
配置引用
[ '$serviceManager' => [ // Will validate all services of this service manager as belonging // to SomeInterface 'service_type' => '\MyApp\SomeInterface', 'config' => [ 'invokables' => [ 'Foo' => '\MyApp\Foo' ], // You can use ZfDiConfig here, too! 'di' => [ 'Bar' => [ 'class' => '\Bar', 'args' => ['%my_app.bar'] ] ] ], // or, you could use a config reference // 'config' => '%my_app.custom_manager' ] ]
扩展 ZfDiConfig
您可以使用自定义插件来扩展 ZfDiConfig。插件必须实现 \Aeris\ZfDiConfig\ServiceManager\ConfigPlugin\ConfigPluginInterface
,并在您的模块配置中注册。
示例
假设您想创建一个用于解析 Doctrine EntityRepository
对象的插件。我们希望能够像这样使用它
// module.config.php return [ 'service_manager' => [ 'di' => [ 'FooService' => [ 'class' => 'MyApp\FooService', 'setters' => [ 'barRepo' => '$repo:MyApp\Entity\Bar' ] ] ] ] ];
首先我们实现插件逻辑
namespace MyApp\ServiceManager\ConfigPlugin; use Aeris\ZfDiConfig\ServiceManager\ConfigPlugin\AbstractConfigPlugin; class DoctrineRepositoryPlugin extends AbstractConfigPlugin { public function resolve($pluginConfig) { // Grab the Doctrine EntityManager from the service locator $entityManager = $this->serviceLocator->get('entity_manager'); // Return the configured repository return $entityManager->get($pluginConfig['entity_class']); } public function configFromString($string) { // Convert a short-form config into an array return [ 'entity_class' => $string; ] } }
现在我们只需要注册插件
/// module.config.php return [ 'zf_di_config' => [ 'plugins' => [ [ 'class' => 'MyApp\ServiceManager\ConfigPlugin\DoctrineRepositoryPlugin', 'name' => '$repo', 'short_name' => '$repo:' ] ] ] ];
然后您就可以使用了!