通过插件管理器提供的懒惰服务

时间:2016-10-13 10:16:39

标签: php zend-framework2

我尝试通过自定义插件管理器(而不是服务管理器)在ZF2中使用Lazy Services

插件管理器看起来像这样。

use Zend\ServiceManager\AbstractPluginManager;
use Zend\ServiceManager\Exception\RuntimeException;

class EntityServiceManager extends AbstractPluginManager
{
    protected $autoAddInvokableClass = false;

    public function validatePlugin($service)
    {
        if ($service instanceof EntityServiceInterface) {
            return;
        }

        throw new RuntimeException(sprintf(
            'Services created by \'%s\' must be of type \'%s\'; \'%s\' provided in \'%s\'.',
            get_called_class(),
            'EntityServiceInterface',
            (is_object($service) ? get_class($service) : gettype($service)),
            __METHOD__
        ));
    }
}

根据文件;我已经配置了服务' UserService'通过这个插件管理器加载延迟。

'service_manager' => [
    'factories' => [
        'Zend\\ServiceManager\\Proxy\\LazyServiceFactory'
            => 'Zend\\ServiceManager\\Proxy\\LazyServiceFactoryFactory',
    ],
],
'lazy_services' => [
    'class_map' => [
        'User\\Entity\\User' => 'User\\Service\\UserService',
    ],
],
'entity_service_manager' => [
    'delegators' => [
        'User\\Entity\\User' => [
            'Zend\\ServiceManager\\Proxy\\LazyServiceFactory',
        ],
    ],
    'factories' => [
        'User\\Entity\\User' => 'User\\Factory\\Service\\UserServiceFactory'
    ],
],

问题是LazyServiceFactory已在ServiceManager中注册,因此在通过$entityServiceManager->get('Spectrum\\User\\Entity\\User')请求服务时无法找到。{/ p>

错误是:

  

可捕获的致命错误:传递给Zend \ ServiceManager \ Proxy \的参数1 \ LazyServiceFactory :: __ construct()必须是ProxyManager \ Factory \ LazyLoadingValueHolderFactory的实例,没有给出

这是因为插件管理器会将工厂创建为可调用的,而不是通过已注册的LazyServiceFactoryFactory

我尝试向插件管理器提供对等管理器,以允许它通过父母找到工厂'服务经理。

`$entityServiceManager->addPeeringServiceManager($serviceManager);`

这允许找到工厂,但无法在validatePlugin()方法中验证。

  

的Zend \的ServiceManager \异常\的RuntimeException'使用' EntityServiceManager'创建的服务'服务必须是' EntityServiceInterface'; ' Zend的\的ServiceManager \代理\ LazyServiceFactory'在EntityServiceManager :: validatePlugin'。'

中提供

如何使用插件管理器注册延迟服务?

1 个答案:

答案 0 :(得分:1)

我想你必须在你的插件管理器中手动注册LazyServiceFactory并为它提供一个自定义工厂,它从你的插件管理器的父服务定位器获取它:

'entity_service_manager' => [
    'delegators' => [
        'User\\Entity\\User' => [
            'Zend\\ServiceManager\\Proxy\\LazyServiceFactory',
        ],
    ],
    'factories' => [
        'User\\Entity\\User' => 'User\\Factory\\Service\\UserServiceFactory',
        'Zend\\ServiceManager\\Proxy\\LazyServiceFactory' => function ($pluginManager) {
            return $pluginManager->getServiceLocator()->get('Zend\\ServiceManager\\Proxy\\LazyServiceFactory');
        }
    ],
],

未经测试,但应该给你一个想法。需要从父服务定位器获取实例的方法,以避免工厂的双重实例化(一次用于全局服务管理器,一次用于插件管理器)。

<强>更新 正如评论中所指出的,插件管理器不允许创建LazyServiceFactory。我可以想到两种方法:

1)没有任何迹象表明validatePlugin方法只能检查并传递一个插件。在您自己实施validatePlugin方法时,您也可以允许创建LazyServiceFactory。这可能不是最好的方法,因为插件管理器应该坚持返回一个接口。

2)您可以在LazyServiceFactory的工厂中创建LazyServiceFactory的实例,而不是依赖插件管理器通过工厂创建EntityServiceManager。使用setService方法:

class YourPluginManagerFactory extends AbstractPluginManagerFactory
{
    const PLUGIN_MANAGER_CLASS = 'EntityServiceManager';

    public function __invoke(ContainerInterface $container, $name, array $options = null)
    {
        $instance = parent::__invoke($container, $name, $options);
        $lazyFactory = $container->get(LazyServiceFactory::class);
        $instance->setService(LazyServiceFactory::class, $lazyFactory);
    }
}

应该绕过validatePlugin方法的检查。

3)作为最后一个想法,虽然不符合依赖注入,但您的插件管理器会收到父服务管理器的实例作为constructor的第一个参数。从那里你可以和工厂一样做。