[英]Using AbstractPluginManager with Zend Expressive 3
我想將實現通用接口的對象數組注入到我的一項服務中。 我正在使用zend servicemanager作為DI容器。 我已經閱讀文檔很多時間了,在我看來AbstractPluginManager是必經之路。 我一直無法使它工作。 有沒有我可以看的使用AbstractPluginManager + Zend Expressive 3的示例?
我的最終目標是將所有實現通用接口的注冊類動態注入到我的服務中。
例:
interface I{}
class A implements I{}
class B implements I{}
class C{}
我的服務
__construct(array Iimplementations){...}
$service = $container->get('myservice')
$service has Iimplementations
提前致謝
AbstractPluginManager主要用於驗證和過濾器插件。 您可以創建類,並且在驗證時可以傳遞特定的配置,從而使過濾器或驗證器可重復使用。
您正在尋找的可能是抽象工廠 。 您只需注冊一次工廠,即可為您創建服務。 在您的情況下具有一組特定的依賴性。
interface I{}
class A implements I{}
class B implements I{}
class MyAbstractFactory implements AbstractFactoryInterface
{
public function canCreate(ContainerInterface $container, $requestedName)
{
return in_array('I', class_implements($requestedName), true);
}
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new $requestedName(
$container->get(DependencyFoo::class),
$container->get(DependencyBar::class)
);
}
}
// config/autoload/dependencies.global.php
return [
'dependencies' => [
'factories' => [
// ...
],
'abstract_factories' => [
MyAbstractFactory::class,
],
],
];
如果每個類的依賴項都不相同,您也可以發瘋並使用反射來檢測依賴項,但這會增加很多開銷。 我認為創建單獨的工廠更加容易且更具維護性。 然后是zend-expressive-tooling ,這是一個cli工具,可以創建工廠,處理程序和中間件。
/*Getting I concrete implementations via the plugin manager will ensure the implementation of the I interface*/
class IPluginManager extends AbstractPluginManager
{
protected $instanceOf = I::class;
public function getIConcreteImplementations()
{
$concreteImpl = [];
foreach(array_keys($this->factories) as $key)
{
$concreteImpl[] = $this->get($key);
}
return $concreteImpl;
}
}
/*IPluginManagerFactory*/
class TransactionSourcePluginManagerFactory
{
const CONFIG_KEY = 'i-implementations-config-key';
public function __invoke(ContainerInterface $container, $name, array $options = null)
{
$pluginManager = new IPluginManager($container, $options ?: []);
// If this is in a zend-mvc application, the ServiceListener will inject
// merged configuration during bootstrap.
if ($container->has('ServiceListener')) {
return $pluginManager;
}
// If we do not have a config service, nothing more to do
if (! $container->has('config')) {
return $pluginManager;
}
$config = $container->get('config');
// If we do not have validators configuration, nothing more to do
if (! isset($config[self::CONFIG_KEY]) || !
is_array($config[self::CONFIG_KEY])) {
return $pluginManager;
}
// Wire service configuration for validators
(new Config($config[self::CONFIG_KEY]))->configureServiceManager($pluginManager);
return $pluginManager;
}
}
/*In the ConfigProvider of the module or global config*/
class ConfigProvider
{
/**
* Returns the configuration array
*
* To add a bit of a structure, each section is defined in a separate
* method which returns an array with its configuration.
*
*/
public function __invoke() : array
{
return [
'dependencies' => $this->getDependencies(),
'routes' => $this->getRoutes(),
'i-implementations-config-key' => $this->getIConcreteImplementations(),
];
}
public function getIConcreteImplementations() : array
{
return [
'factories' => [
A::class => AFactory::class,
B::class => InvokableFactory::class,
],
];
}
}
/*I can now be sure that I am injecting an array of I implementations into my Service*/
class ServiceFactory
{
public function __invoke(ContainerInterface $container) : Service
{
$pluginManager = $container->get(IPluginManager::class);
$impl = $pluginManager->getIConcreteImplementations();
return new Service($impl);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.