没有服务定位器的ZF2依赖注入到Controller对象上

时间:2015-05-14 07:55:10

标签: php dependency-injection zend-framework2 service-locator

我一直在阅读ZF2服务定位器组件,可以说我理解它是如何被使用的。然而,我有一个问题,我觉得它很愚蠢,但问一下也没什么坏处。

我希望在我的模块中有一个名为Component的命名空间,我可以将通用代码放在如FunctionComponent.php,MailerComponent.php或ExcelComponent.php中。这将允许我在我的控制器中做一些事情。

我想尝试的是让控制器定义他们有兴趣使用的组件(见下文):

class SalesController extends AbstractController
{
  protected $components = ['Excel'];

  //In some action
  public function exportAction()
  {
    $data = ['data to be exported'];
    /**
      $data : data to be exported
      boolean : Whether to force download or save the file in a dedicated location
    */
    $this->Excel->export($data, true);
  }
}

想法是创建一个ComponentCollection,它可能实现FactoryInterface或ServiceLocatorInterface,然后让它在我的Module类中触发MvcEvent时检查每个控制器,并让ComponentCollection注入所有控制器组件并使它们可以访问而不使用服务定位器如下图所示:

$excel = $sm->get('Application\Component\Excel');

我很清楚这可能看起来像是一个令人生畏的问题,但我觉得学习框架的最好方法就是玩弄它并尝试做到难以想象。

1 个答案:

答案 0 :(得分:1)

您应该在某处创建BaseController,然后从Controllers扩展您的所有BaseController。然后,您可以在BaseController中注入依赖项,并在孩子的任何地方使用。例如,我在我的Controller中执行此操作以设置标题:

<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

class BaseController extends AbstractActionController
{

    /**
     * Sets the head title for every page
     *
     * @param string $title
     */
    public function setHeadTitle($title)
    {
        $viewHelperManager = $this->getServiceLocator()->get('ViewHelperManager');
        // Getting the headTitle helper from the view helper manager
        $headTitleHelper = $viewHelperManager->get('headTitle');

        // Setting a separator string for segments
        $headTitleHelper->setSeparator(' - ');

        // Setting the action, controller, module and site name as title segments
        $siteName = 'Ribbon Cutters';
        $translator = $this->getServiceLocator()->get('translator');
        $title = $translator->translate($title);
        $headTitleHelper->append(ucfirst($title));
        $headTitleHelper->append($siteName);
    }

}

您可以定义属性,而不是定义方法。

public $headTitleHelper

并在BaseController

的构造函数中指定它
$this->headTitleHelper = $this->getServiceLocator()->get('ViewHelperManager')->get('headTitle');

现在您可以在子控制器中使用$this->headTitleHelper

然后

<?php

namespace Application\Controller;

use Zend\View\Model\ViewModel;
use Application\Controller\BaseController;

class IndexController extends BaseController
{

    /**
     * Property for setting entity manager of doctrine
     */
    protected $em;

    /**
     * landing page
     *
     * @return ViewModel
     */
    public function indexAction()
    {

        $this->setHeadTitle('Welcome');  // Welcome - Ribbon Cutters

        $viewModel = new ViewModel();

        return $viewModel;
    }



    /**
     * Sets and gives Doctrine Entity Manager
     *
     * @return Doctrine Entity Manager
     */
    protected function getEntityManager()
    {
        if (null === $this->em) {
            $this->em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
        }
        return $this->em;
    }
}

我认为这可以帮助你。