drt5813 2016-05-05 13:21
浏览 49
已采纳

zend框架2:如何正确地将工厂注入到控制器中以获得不同的映射器类?

I'm using Apigility, built on ZF2. Once request is dispatched to the controller's action, I need to choose proper adapter to hanle request - based on incomming parameters.

Normally, Controller is instantiated by ControllerFactory, where you can provide all dependencies, let say I need som kind of mapper class to be injected. It's easy, if I know, which one I will use in within the controller. It's problematic if I need to let controller decide which mapper to use.

Let's say user is requesting something like getStatus with param 'adapter1' and another user is accessing same action, but with param 'adapter2'.

So, I need to inject adapter1 mapper OR adapter2 mapper, which has similar interface, but different constructor.

What's the proper way how to handle this situation ?

On possible solution is to supply some kind of factory method, which will provide requested adapter, but - using the SM int the model class should be avoided.

Another way is to use SM directly in within Controller's action, but this in not best approach, because I can't reuse 'switch-case' logic for another actions / controllers.

How to handle this, please ?

  • 写回答

1条回答 默认 最新

  • duanlian1320 2016-05-06 07:51
    关注

    You could use controller plugins for this.

    Like that you can get the adapter inside your controller when you need it without injecting a ServiceManager and without adding all the logic to the factory. The adapter will only be instantiated when you request it in your controller action method.

    First you need to create your controller plugin class (extending 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
    
        }
    }
    

    Then a factory to inject your service in the 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);
        }
    }
    

    Then you need to register your plugin in your module.config.php:

    <?php
    return array(
        //...
        'controller_plugins' => array(
            'factories' => array(
                'AdapterPlugin' => 'Application\Controller\Plugin\Factory\AdapterPluginFactory',
            )
        ),
        // ...
    );
    

    Now you can use it inside your controller action like this:

    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);
    }
    

    Read more on controller plugins here in the documentation

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料