Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 通过插件管理器提供惰性服务_Php_Zend Framework2 - Fatal编程技术网

Php 通过插件管理器提供惰性服务

Php 通过插件管理器提供惰性服务,php,zend-framework2,Php,Zend Framework2,我试图通过自定义插件管理器(而不是服务管理器)在ZF2中使用 插件管理器如下所示 use Zend\ServiceManager\AbstractPluginManager; use Zend\ServiceManager\Exception\RuntimeException; class EntityServiceManager extends AbstractPluginManager { protected $autoAddInvokableClass = false;

我试图通过自定义插件管理器(而不是服务管理器)在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\\User')请求服务时无法找到该工厂。

错误是:

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

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

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

`$entityServiceManager->addPeeringServiceManager($serviceManager);`
这允许找到工厂,但无法在
validatePlugin()
方法中进行验证

Zend\ServiceManager\Exception\RuntimeException,消息为“EntityServiceManager”创建的服务必须为“EntityServiceInterface”类型“EntityServiceManager::validatePlugin”中提供了Zend\ServiceManager\Proxy\LazyServiceFactory”


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

我想您必须在插件管理器中手动注册
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) 您可以使用
setService
方法在
EntityServiceManager
的工厂中创建
LazyServiceFactory
实例时,插入
LazyServiceFactory
,而不是依赖插件管理器通过工厂创建
LazyServiceFactory

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) 最后一个想法是,虽然不符合依赖项注入,但您的插件管理器会接收父服务管理器的实例作为
构造函数的第一个参数。在那里,你可以像在工厂里那样做。

@Ocramius?:-p当我添加时,确实会发生这种情况(在版本2.5.1之后,它已被删除,这将使您的建议成为更好的选择)。现在的问题是,
validatePlugin()
方法引发第二个异常,因为
LazyServiceFactory
不是
EntityServiceInterface
的实例。我看到所有其他插件管理器都执行类似的检查,因此必须有一种方法来正确配置它。