aeris/zf-di-config

该软件包最新版本(v1.3.2)没有提供许可证信息。

为 ZF2 ServiceManager 提供可配置的依赖注入

v1.3.2 2015-08-20 18:58 UTC

This package is not auto-updated.

Last update: 2024-09-18 09:12:13 UTC


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:'
            ]
        ]
    ]
];

然后您就可以使用了!