在Apigility驱动的ZF2应用程序中,我想使用自定义Hydrator
。
Module
课程
class Module implements ApigilityProviderInterface {
...
public function getServiceConfig() {
return array(
'factories' => array(
...
'MyNamespace\\Hydrator\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
...
);
}
}
module.config.php
...
'zf-hal' => array(
'metadata_map' => array(
...
'Portfolio\\V2\\Rest\\Project\\ProjectEntity' => array(
'entity_identifier_name' => 'id',
'route_name' => 'portfolio.rest.project',
'route_identifier_name' => 'id',
// 'hydrator' => 'Zend\\Stdlib\\Hydrator\\ClassMethods',
'hydrator' => 'MyNamespace\\Hydrator\\ProjectHydrator',
),
...
),
),
...
当集合被检索时被忽略,但这是另一个问题(s。here)。当需要单个实体时,waterratin机制启动,但它不使用我的工厂,以创建实例。
经过一些调试后,我来到ZF\Hal\Metadata\Metadata#setHydrator(...)
代码中的这个地方:
if (is_string($hydrator)) {
if (null !== $this->hydrators
&& $this->hydrators->has($hydrator)
) {
$hydrator = $this->hydrators->get($hydrator);
} elseif (class_exists($hydrator)) {
$hydrator = new $hydrator(); // <-- here
}
}
直接创建自定义Hydrator
。 (在我的情况下,它会导致致命错误,因为它已经尝试在ProjectHydrator#imageService
上执行一个未设置的方法)。我查看了Metadata#hydrators
(Zend\Stdlib\Hydrator\HydratorPluginManager
类型)并且只找到了四个默认invocables
,这就是null !== $this->hydrators && $this->hydrators->has($hydrator)
为false
并尝试直接实例化的原因
所以,我想,我必须注册我的定制保湿器。我在哪里/怎么做?
修改:
我将工厂代码从Module#getServiceConfig()
移至Module#getHydratorConfig()
:
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'MyNamespace\\Hydrator\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
$projectHydrator->setImageService($serviceManager->get('Portfolio\V2\Rest\ImageService'));
return $projectHydrator;
}
),
);
}
module.config.php
中的配置数组相同(需要Factory
类):
module.config.php
return array(
...
'hydrators' => array(
'factories' => array(
'MyNamespace\\Hydrator\\ProjectHydrator' => 'MyNamespace\\Hydrator\\ProjectHydratorFactory',
),
),
);
但它以错误结束:
的Zend \的ServiceManager \异常\ ServiceNotFoundException的
文件: /var/www/my-project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:550 消息:Zend \ Stdlib \ Hydrator \ HydratorPluginManager :: get无法 为Portfolio \ V2 \ Rest \ ImageService
获取或创建实例
答案 0 :(得分:5)
您在使用getHydratorConfig
进行修改时所执行的操作是正确的,因为您在工厂方法中试图从保护器插件管理器中获取图像服务,因此导致您看到的错误消息。
解决方案很简单,与其他插件管理器一样,您需要在hydrator管理器实例上调用getServiceLocator()
以获取主服务定位器(也称为服务管理器)
因此,对工厂方法进行一些小改动应该可以解决问题......
public function getHydratorConfig() {
return array(
'factories' => array(
// V2
'MyNamespace\\Hydrator\\ProjectHydrator' => function(ServiceManager $serviceManager) {
$projectHydrator = new ProjectHydrator();
// get the image service from the main service locator
$imageService = $serviceManager->getServiceLocator()->get('Portfolio\V2\Rest\ImageService');
$projectHydrator->setImageService($imageService);
return $projectHydrator;
}
),
);
}
工作原理:作为参数传递给闭包的实例是Zend\Stdlib\Hydrator\HydratorPluginManager
。 HydratorPluginManager
继承自Zend\ServiceManager\AbstractPluginManager
的{{1}}的孩子。但是方法Zend\ServiceManager\ServiceManager
在ServiceManager#get(...)
中被逻辑覆盖,并且仅提供加水器。然而,它的父类实现了HydratorPluginManager
,因此我们访问其内部Zend\ServiceManager\ServiceLocatorAwareInterface
和ServiceLocator
以及整套可用服务。
顺便说一句,我通常更喜欢在工厂方法(代码中为ServiceLocator
)中命名serviceLocator变量,以便它反映实际使用的插件管理器,因此对于水箱工厂,{{1} },对于表单工厂,$serviceManager
,等等。我保留使用$hydrators
仅指代主服务管理器。我发现这样做是一个有用的提示,对于不在该特定经理中的任何依赖项,必须进行$formElemements
调用。
答案 1 :(得分:-1)
快速回复。将HydratorManager
替换为自定义的。{/ p>
在您的全局配置中:
return array(
'service_manager' => array(
'factories' => (
'HydratorManager' => 'MyNamespace\Hydrator\HydratorManagerFactory',
),
),
);
myNameSpace对象\保湿\ HydratorManagerFactory.php:
<?php
namespace MyNamespace\Hydrator;
use Zend\Mvc\Service\HydratorManagerFactory as BaseHydratorManagerFactory;
class HydratorManagerFactory extends BaseHydratorManagerFactory
{
const PLUGIN_MANAGER_CLASS = 'MyNamespace\Hydrator\HydratorPluginManager';
}
myNameSpace对象\保湿\ HydratorPluginManager.php
<?php
namespace MyNamespace\Hydrator;
use Zend\Stdlib\Hydrator\HydratorPluginManager as BaseHydratorPluginManager;
class HydratorPluginManager extends BaseHydratorPluginManager
{
protected $factories = array(
'mynamespacehydratorprojecthydrator' => 'MyNamespace\\Hydrator\\ProjectHydratorFactory',
);
}
注意工厂将收到Zend\ServiceManager\AbstractPluginManager
的实例。您可以使用调用方法$services->getServiceLocator()