0

Я читаю компонент ZF2 Service Locator и могу сказать, что я понимаю, как он используется. У меня есть, однако, вопрос, который я считаю его глупым, но это не помешает спросить.ZF2 Инъекция зависимостей от объектов контроллера без локатора сервисов

Я хочу иметь пространство имен внутри моего модуля под названием «Компонент», где я могу указать общий код, например, как функцииComponent.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, а затем дайте ему проверить каждый контроллер, когда MvcEvent была запущена внутри моего класса модуля и имеет ComponentCollection впрыскивать все компоненты контроллера и сделать их доступными без использования локатора сервиса, как показано ниже:

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

Мне хорошо известно, что это может показаться сложным спросом, но я чувствую, что лучший способ изучить структуру среди прочего - это поиграть с ней и попытаться сделать невообразимое.

+0

Я не совсем уверен, что вы здесь задаете. Самый эффективный способ ввода зависимостей контроллеров - через локатор сервисов (с использованием фабрики). В противном случае альтернативой (контейнер DI) в Zend будет компонент Zend \ Di. Они оба решают одну и ту же проблему. Предпочтение с ZF2 должно использоваться с помощью Locator. – AlexP

+0

Идея состоит в том, чтобы использовать те же инструменты, предоставляемые каркасом, но по-другому вместо того, чтобы получать определенный компонент через локатор сервисов, мы скорее определяем свойство компонентов с массивом компонентов, которые мы хотели бы использовать в нашем контроллере, и как эти компоненты создаются можно сделать в фоновом режиме, когда разработчик может пойти как $ ComponentName-> functionCall ($ parameters) в отличие от $ component = $ sl-> get ('Namespace \ Component \ ActualComponent') каждый раз, когда вы хотите использовать компонент. – Maximum86

+0

Вам следует избегать использования сервис-менеджера * в * ваших сервисах (включая контроллер). «Компоненты», которые вы упомянули, являются зависимостями класса *, то есть их следует вводить в требуемую службу (через локатор сервисов или DI), чтобы затем они были доступны как свойства экземпляра (т. Е. '$ This-> myService').Если вы хотите использовать метод * удобства *, такой как '$ ComponentName-> functionCall ($ parameters)' все, что вам нужно будет сделать, это реализовать волшебный метод '__call()' и определить, соответствует ли запрошенное имя метода определенному класса. – AlexP

ответ

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

Я думаю, что это может помочь вам.

+0

Спасибо, Билал, я думаю, что смогу приготовить что-нибудь вокруг вашего решения, возможно, больше из объекта плагина или чего-то еще. Я дам вам знать об итогах .... :-) – Maximum86