0

我一直在閱讀ZF2服務定位器組件,並可以說我明白它是如何使用的。不過,我有一個問題,我認爲它很愚蠢,但不會因爲問問題而受傷。ZF2依賴注入到沒有服務定位器的控制器對象

我想在我的模塊內部有一個名爲Component的名稱空間,我可以在其中放入泛型代碼,比如說FunctionsComponent.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); 
    } 
} 

的想法是創建一個可能實現FactoryInterface一個ComponentCollection或ServiceLocatorInterface然後讓它檢查每個控制器,當MvcEvent已經觸發了我的模塊類中,並有ComponentCollection注入所有的控制器組件,使他們不使用服務定位器訪問,如下圖所示:

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

我很清楚,這看起來像是一個令人望而生畏的問題,但我覺得學習框架的最好方法就是玩弄它並嘗試做出難以想象的事情。

+0

我不完全確定你在這裏問什麼。注入控制器依賴關係的最有效方法是通過服務定位器(使用工廠)。否則,Zend中的替代(一個DI容器)將成爲'Zend \ Di'組件。他們都解決了同樣的問題 - ZF2的偏好應該使用服務定位器。 – AlexP

+0

這個想法是使用框架提供的相同的工具,但不同的是,通過服務定位器來獲取特定的組件,而不是通過我們想要在控制器中使用的組件數組來定義組件屬性,以及如何製作這些組件可以在後臺完成,開發人員可以在每次使用組件時使用$ ComponentName-> functionCall($ parameters),而不是$ component = $ sl-> get('Namespace \ Component \ ActualComponent')。 – Maximum86

+0

您應該避免在您的服務(包括控制器)中使用服務管理器*。你提到的'組件'是類*依賴關係*,意味着它們應該被注入所需的服務(通過服務定位器或DI),因此它們可以作爲實例屬性(即'$ this-> myService')。如果你希望有一個方便的方法,比如'$ ComponentName-> functionCall($ parameters)',你需要做的就是實現一個'__call()'魔術方法,並確定請求的方法名是否與一個已定義的一流的財產。 – AlexP

回答

1

您應該在某處創建BaseController,然後從BaseController擴展您的所有Controllers。然後你可以在你的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; 
    } 
} 

,我認爲這可以幫助你。

+0

感謝Bilal我認爲我可以在你的解決方案上做些什麼或許更多的是插件對象或其他東西。我會讓你知道結果.... :-) – Maximum86