我正在尝试通过自定义插件管理器(而不是服务管理器(在 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__
));
}
}
根据文档;我已经将服务"用户服务"配置为通过此插件管理器延迟加载。
'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
已注册到服务管理器,因此在通过 $entityServiceManager->get('Spectrum''User''Entity''User')
请求服务时找不到。
错误是:
可捕获的致命错误:参数 1 传递给 Zend''ServiceManager''Proxy''LazyServiceFactory::__construct(( 必须是 ProxyManager''Factory''LazyLoadValueHolderFactory 的实例,没有给出
这是因为插件管理器会将工厂创建为可调用的,而不是通过注册的LazyServiceFactoryFactory
。
我尝试为插件管理器提供一个对等管理器,以允许它通过"父"服务管理器找到工厂。
`$entityServiceManager->addPeeringServiceManager($serviceManager);`
这允许找到工厂,但它无法在validatePlugin()
方法中进行验证。
Zend''ServiceManager''Exception''RuntimeException",消息"由'EntityServiceManager'创建的服务"的类型必须是'EntityServiceInterface';'Zend''ServiceManager''Proxy''LazyServiceFactory' 在 '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
。严格来说,这可能不是最好的方法,因为插件管理器应该坚持返回一个接口。
2(与其像上面那样依靠插件管理器通过工厂创建LazyServiceFactory
,不如使用setService
方法在EntityServiceManager
工厂中创建时注入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(最后一个想法,虽然不符合依赖注入,但你的插件管理器接收父服务管理器的实例作为constructor
的第一个参数。从那里您可以像工厂一样做同样的事情。