zend 框架 2:如何正确地将工厂注入控制器以获得不同的映射器 类?
zend framework 2: how to properly inject factory to controller to get different mapper classes?
我正在使用基于 ZF2 构建的 Apigility。一旦请求被分派给控制器的操作,我需要选择合适的适配器来处理请求——基于传入的参数。
通常,Controller 由 ControllerFactory
实例化,您可以在其中提供所有依赖项,假设我需要注入某种映射器 class。这很容易,如果我知道,我将在控制器中使用哪一个。如果我需要让控制器决定使用哪个映射器,这是有问题的。
假设用户使用参数 'adapter1'
请求类似 getStatus
的内容,而另一个用户正在访问相同的操作,但使用参数 'adapter2'
.
因此,我需要注入 adapter1
映射器或 adapter2
映射器,它们具有相似的接口,但构造函数不同。
处理这种情况的正确方法是什么?
可能的解决方案是提供某种工厂方法,它将提供请求的适配器,但是 - 应避免使用 SM int 模型 class。
另一种方法是直接在 Controller 的操作中使用 SM,但这不是最佳方法,因为我无法将 'switch-case' 逻辑重新用于其他操作/控制器。
请问如何处理?
您可以为此使用控制器插件。
就像这样,您可以在需要时将适配器放入控制器中,而无需注入 ServiceManager
并且无需将所有逻辑添加到工厂。适配器只会在您在控制器操作方法中请求时被实例化。
首先你需要创建你的控制器插件class(扩展Zend\Mvc\Controller\Plugin\AbstractPlugin
):
<?php
namespace Application\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
class AdapterPlugin extends AbstractPlugin{
protected $adapterProviderService;
public function __constuct(AdapterProviderService $adapterProviderService){
$this->adapterProviderService = $adapterProviderService;
}
public function getAdapter($param){
// get the adapter using the param passed from controller
}
}
然后工厂注入你的服务在class:
<?php
namespace Application\Controller\Plugin\Factory;
use Application\Controller\Plugin\AdapterPlugin;
class AdapterPluginFactory implements FactoryInterface
{
/**
* @param ServiceLocatorInterface $serviceController
* @return AdapterPlugin
*/
public function createService(ServiceLocatorInterface $serviceController)
{
$serviceManager = $serviceController->getServiceLocator();
$adapterProvicerService = $serviceManager>get('Application\Service\AdapterProviderService');
return new AdapterPlugin($adapterProviderService);
}
}
然后你需要在你的 module.config.php
:
中注册你的插件
<?php
return array(
//...
'controller_plugins' => array(
'factories' => array(
'AdapterPlugin' => 'Application\Controller\Plugin\Factory\AdapterPluginFactory',
)
),
// ...
);
现在您可以像这样在控制器操作中使用它:
protected function controllerAction(){
$plugin = $this->plugin('AdapterPlugin');
// Get the param for getting the correct adapter
$param = $this->getParamForAdapter();
// now you can get the adapter using the plugin
$plugin->getAdapter($param);
}
阅读更多关于控制器插件的信息here in the documentation
我正在使用基于 ZF2 构建的 Apigility。一旦请求被分派给控制器的操作,我需要选择合适的适配器来处理请求——基于传入的参数。
通常,Controller 由 ControllerFactory
实例化,您可以在其中提供所有依赖项,假设我需要注入某种映射器 class。这很容易,如果我知道,我将在控制器中使用哪一个。如果我需要让控制器决定使用哪个映射器,这是有问题的。
假设用户使用参数 'adapter1'
请求类似 getStatus
的内容,而另一个用户正在访问相同的操作,但使用参数 'adapter2'
.
因此,我需要注入 adapter1
映射器或 adapter2
映射器,它们具有相似的接口,但构造函数不同。
处理这种情况的正确方法是什么?
可能的解决方案是提供某种工厂方法,它将提供请求的适配器,但是 - 应避免使用 SM int 模型 class。
另一种方法是直接在 Controller 的操作中使用 SM,但这不是最佳方法,因为我无法将 'switch-case' 逻辑重新用于其他操作/控制器。
请问如何处理?
您可以为此使用控制器插件。
就像这样,您可以在需要时将适配器放入控制器中,而无需注入 ServiceManager
并且无需将所有逻辑添加到工厂。适配器只会在您在控制器操作方法中请求时被实例化。
首先你需要创建你的控制器插件class(扩展Zend\Mvc\Controller\Plugin\AbstractPlugin
):
<?php
namespace Application\Controller\Plugin;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
class AdapterPlugin extends AbstractPlugin{
protected $adapterProviderService;
public function __constuct(AdapterProviderService $adapterProviderService){
$this->adapterProviderService = $adapterProviderService;
}
public function getAdapter($param){
// get the adapter using the param passed from controller
}
}
然后工厂注入你的服务在class:
<?php
namespace Application\Controller\Plugin\Factory;
use Application\Controller\Plugin\AdapterPlugin;
class AdapterPluginFactory implements FactoryInterface
{
/**
* @param ServiceLocatorInterface $serviceController
* @return AdapterPlugin
*/
public function createService(ServiceLocatorInterface $serviceController)
{
$serviceManager = $serviceController->getServiceLocator();
$adapterProvicerService = $serviceManager>get('Application\Service\AdapterProviderService');
return new AdapterPlugin($adapterProviderService);
}
}
然后你需要在你的 module.config.php
:
<?php
return array(
//...
'controller_plugins' => array(
'factories' => array(
'AdapterPlugin' => 'Application\Controller\Plugin\Factory\AdapterPluginFactory',
)
),
// ...
);
现在您可以像这样在控制器操作中使用它:
protected function controllerAction(){
$plugin = $this->plugin('AdapterPlugin');
// Get the param for getting the correct adapter
$param = $this->getParamForAdapter();
// now you can get the adapter using the plugin
$plugin->getAdapter($param);
}
阅读更多关于控制器插件的信息here in the documentation