2017-02-23 55 views
1

我不知道如何制定問題,所以隨意編輯它。ZF2主義 - 如何處理需要特定ID的依賴注入

我目前的情況如下: 我有一個工廠類,它實例化一個窗體類。依賴注入(DI)通過構造函數注入完成。我的問題是,這個表單元素有一個Doctrine ObjectMultiCheckbox需要一個findby方法。對於這個findby-method我需要某個實體的ID,但是我不能將ID通過工廠類傳遞給表單。

我的問題是,我該如何處理這種情況?什麼是最好的方法?

比方說,這是我的工廠類:

class CustomerFormFactory implements FactoryInterface 
{ 
    /** 
    * Create service 
    * 
    * @param ServiceLocatorInterface $serviceLocator 
    * @return Form 
    */ 
    public function createService(ServiceLocatorInterface $serviceLocator) 
    { 
     $em = $serviceLocator->get('Doctrine\ORM\EntityManager'); 
     return new CustomerForm($em); 
    } 
} 

而且我通過這樣的服務定位器獲取表單:

$customerForm = $this->getServiceLocator()->get('CustomerForm'); 

我怎樣才能ID傳遞給服務定位?如果表單元素需要一個特定的ID,是不是會破壞DI和服務的目的?我應該去「經典」的方法和實例化表單元素由我自己是這樣的:

$customerForm = new CustomerForm(EntityManager $em, int $id); 

我真的不知道我應該做什麼,或者是處理的最佳方式。

回答

3

爲了將選項插入到表單中,您可以使用工廠類的CreationOptions

因此,讓我們開始設置FormElementManager(我們的表單元素的serviceLocator)的配置。

在您Module.php

use Zend\ModuleManager\Feature\FormElementProviderInterface; 

class Module implements FormElementProviderInterface 
{ 
    // your module code 

    public function getFormElementConfig() 
    { 
     return [ 
      'factories' => [ 
       'myForm' => \Module\Form\MyFormFactory::class 
      ] 
     ]; 
    } 
} 

後,我們已經成立了,我們應該創建我們的工廠,它返回的形式,包括它的依賴的configruation。我們還插入了我們可以在表單類中重用的選項。

use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\MutableCreationOptionsTrait; 
use Zend\ServiceManager\ServiceLocatorInterface; 

class MyFormFactory implements FactoryInterface 
{ 
    use MutableCreationOptionsTrait; 

    /** 
    * Create service 
    * 
    * @param ServiceLocatorInterface $serviceLocator 
    * 
    * @return mixed 
    */ 
    public function createService(ServiceLocatorInterface $serviceLocator) 
    { 
     return new MyForm(
      $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager'), 
      'MyForm', 
      $this->getCreationOptions() 
     ); 
    } 
} 

當使用ZF3它是更好地使用\Zend\ServiceManager\Factory\FactoryInterface代替\Zend\ServiceManager\FactoryInterface,因爲這是ZF3與使用的工廠去的方式。在上面的例子中,我使用了ZF2(v2.7.6 zendframework/zend-servicemanager)版本。請參閱類別Zend\ServiceManager\FactoryInterface::class上的評論以將其替換爲ZF3版本。

所以現在,當我們在FormElementManager級呼叫::get('myForm', ['id' => $id])你會得到一個MyForm實例和形式的選擇將包含我們一起傳遞的選項。

所以你的形式可能看起來類似:

class MyForm extends \Zend\Form\Form 
{ 
    public function __construct(
     \Doctrine\Common\Persistence\ObjectManager $entityManager, 
     $name = 'myForm', 
     $options = [] 
    ) { 
     parent::__construct($name, $options); 

     $this->setEntityManager($entityManager); 
    } 

    public function init() { 
     /** add form elements **/ 
     $id = $this->getOption('id'); 
    } 
} 

您還可以創建表格並設置EntityManager的,但是這是一切都取決於你。你不需要使用構造函數注入。

因此,對於你控制器中的〔實施例:

$myForm = $this->getServiceManager()->get('FormElementManager')->get('myForm', ['id' => 1337]); 
$options = $myForm->getOptions(); 
// your options: ['id' => 1337] 

您可能沒有你的控制器內的ServiceManager或定位器爲你使用ZF2.5 +或ZF3所以你一定要注入FormElementManager或將Form類以工廠方式放入Controller。

如果您的表單中沒有任何其他依賴關係,但您想設置選項,則不需要爲每個類創建一個工廠。您可以重新使用InvokableFactory::class,因爲這也會注入creationOptions。

+1

很好的回答!謝謝 :) – Sepultura