php - 通过插件管理器的惰性服务

标签 php zend-framework2

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

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

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\\用户').

错误是:

Catchable fatal error: Argument 1 passed to Zend\ServiceManager\Proxy\LazyServiceFactory::__construct() must be an instance of ProxyManager\Factory\LazyLoadingValueHolderFactory, none given

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

我尝试为插件管理器提供一个对等管理器,以允许它通过“父”服务管理器找到工厂。

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

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

Zend\ServiceManager\Exception\RuntimeException' with message 'Services created by 'EntityServiceManager' must be of type 'EntityServiceInterface'; 'Zend\ServiceManager\Proxy\LazyServiceFactory' provided in 'EntityServiceManager::validatePlugin'.'

如何向插件管理器注册惰性服务?

最佳答案

我猜你必须在你的插件管理器中手动注册 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。严格来说,这可能不是最好的方法,因为插件管理器应该坚持返回的一个接口(interface)。

2) 不像上面那样依赖插件管理器通过工厂创建 LazyServiceFactory,您可以在 中创建时注入(inject) 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) 作为最后一个想法,虽然不符合依赖注入(inject),但您的插件管理器接收父服务管理器的实例作为 constructor 的第一个参数。从那里您可以执行与工厂相同的操作。

关于php - 通过插件管理器的惰性服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40018237/

相关文章:

php - 无法通过 PDO 连接到 AWS RDS

php - Symfony 2 性能优化

php - 代码在 jsfiddle 中工作,但当我将所有代码放入我的网站时不起作用

php - 解析css并创建类名和背景图片的键值数组

mysql - Doctrine 2 大写首字母

php - Zend-Framework2。查询

php - php代码中的错误mysql更新命令

forms - 如何在 Zend Framework 2 中使用自定义表单 View 助手?

zend-framework2 - 在 zf2 查询中选择联合

php - "a"将 Zend2 应用程序与 PHPBB3 身份验证集成的正确方法是什么?