从抽象控制器工厂中访问依赖项

时间:2013-05-23 12:00:30

标签: zend-framework2 abstract-factory

我的应用程序中的大多数控制器都需要能够访问当前登录用户的“帐户”,所以我试图将其注入每个控制器类。这样做的方法似乎是为控制器类创建一个抽象工厂,它可以提供所有依赖项。所以我用一个方法创建了工厂类:

public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
    $controllerClassName = $requestedName.'Controller';

    $controller = new $controllerClassName();

    $account = $serviceLocator->get('Account');
    $controller->setAccount($account);

    return $controller;
}

然而$serviceLocator->get('Account');行给出了错误:

  

Zend \ Mvc \ Controller \ ControllerManager :: get无法获取或创建帐户实例

在控制器操作中调用$this->getServiceLocator()->get('Account')工作正常,为什么这个调用不能在控制器工厂内工作?

或者有更好的方法来实现这个目标吗?

1 个答案:

答案 0 :(得分:2)

查看错误

  

Zend \ Mvc \ Controller \ ControllerManager :: get无法获取或创建帐户实例

ControllerManager没有名为Account的服务,它只有控制器。您需要从控制器管理器获取主服务定位器

$account = $serviceLocator->getServiceLocator()->get('Account');
  

或者有更好的方法来实现这个目标吗?

就个人而言,我发现更好的方法是使用控制器插件作为代理来包装服务

首先使用构造函数创建插件,该构造函数接受您的服务实例作为其参数

<?php
namespace Application\Controller\Plugin;

use Zend\Mvc\Contoller\Plugin\AbstractPlugin;

class Account extends AbstractPlugin
{
    protected $account;

    public function __construct($account)
    {
         $this->account = $account;
    }

    // .. write plugin methods to proxy to your service methods 

    public function getId()
    {
        return $this->account->getId();
    }
}

然后使用Module.php方法将其注册到getControllerPluginConfig()文件中的框架并将闭包定义为工厂以构建插件,并将服务注入其构造函数 p>

<?php
namespace Application;
class Module
{
    public function getControllerPluginConfig()
    {
        return array(
            'factories' => array(
                 'account' => function($sm) {
                      $account = $sm->getServiceLocator()->get('Account')
                      // create a new instance of your plugin, injecting the service it uses
                      $plugin = new \Application\Controller\Plugin\Account($account);
                      return $plugin;
                 },
             ),
        );
    }
}

最后,在您的控制器(任何控制器)中,您可以调用插件方法来访问您的服务

 public function actionIndex()
 {
     $accountId = $this->account()->getId();
 }