2

我有一個表格(Zend\Form\Form),其中包含一些嵌套字段集(Zend\Form\Fieldset)。該建築非常類似於Form Collections tutorial如何在Zend Framework 2中爲表單字段集使用服務?

Storage\Form\MyForm 
|_'Storage\Form\Fieldset\FooFieldset' 
    |_'Storage\Form\Fieldset\BarFieldset' 
|_'Storage\Form\Fieldset\BazFieldset' 
... 

MyForm

class MyForm { 
    public function __construct() 
    { 
     ... 
     $this->add(
      [ 
       'type' => 'Storage\Form\Fieldset\FooFieldset', 
       'options' => [ 
        'use_as_base_fieldset' => true 
       ] 
      ] 
     ); 
    } 
} 

FooFieldset

class FooFieldset extends Fieldset implements InputFilterProviderInterface 
{ 
    public function __construct() 
    { 
     parent::__construct('foo'); 
     $this->setHydrator(new ClassMethodsHydrator())->setObject(new Foo()); // dependencies! 
    } 
} 

它的工作原理,但字段集類有兩個依賴於它。我想注入它們。爲了做到這一點,我創建了一個FooFieldsetFactory並延長了/module/MyModule/config/module.config.php

'service_manager' => [ 
    'factories' => [ 
     'Storage\Form\Fieldset\FooFieldset' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory', 
    ], 
], 

工廠只是被忽略。我想,服務定位器首先嚐試通過名稱空間來查找類,並且只有在找不到任何東西時,纔會查看invokablesfactories。好。然後,我創建了一個別名:

'service_manager' => [ 
    'factories' => [ 
     'Storage\Form\Fieldset\FooFieldset' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory', 
    ], 
], 
'aliases' => [ 
    'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\FooFieldset', 
], 

...,並試圖用它代替的Storage\Form\Fieldset\FooFieldset在我的表單類。但現在我得到一個異常:

的Zend \表格\ FormElementManager :: GET無法獲取或創建存儲\表格\字段集\富

我也直接試過這個實例:

'service_manager' => [ 
    'factories' => [ 
     'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory', 
    ], 
], 

沒有效果,同樣的錯誤。

而且這也沒有工作(同樣的錯誤):

'form_elements' => [ 
    'factories' => [ 
     'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory', 
    ], 
], 

所以對於一個字段的引用服務似乎不起作用。或者我做錯了什麼?

如何使用表單字段集的服務?


UPDATE

有了一些debuggin我發現,我的Foo字段集工廠無法找到,因爲它沒有被添加到Zend\Form\FormElementManagerfactories名單。下面是在Zend\Form\Factory的地方:

enter image description here

所以我的配置

'form_elements' => [ 
    'factories' => [ 
     'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory', 
    ], 
], 

被忽略。如何解決這個問題?


UPDATE其他信息,我如何創建我的Form對象。

/module/Foo/config/module.config.php

return [ 
    'controllers' => [ 
     'factories' => [ 
      'Foo\Controller\My' => 'Foo\Controller\Factory\MyControllerFactory' 
     ] 
    ], 
    'service_manager' => [ 
     'factories' => [ 
      'Foo\Form\MyForm' => 'Foo\Form\Factory\MyFormFactory', 
     ], 
    ], 
]; 

/module/Foo/src/Foo/Form/Factory/MyFormFactory.php

namespace Foo\Form\Factory; 

use ...; 

class MyFormFactory implements FactoryInterface 
{ 

    public function createService(ServiceLocatorInterface $serviceLocator) 
    { 
     $form = new MyForm(); 
     $form->setAttribute('method', 'post') 
      ->setHydrator(new ClassMethods()) 
      ->setInputFilter(new InputFilter()); 
     return $form; 
    } 
} 

/module/Foo/src/Foo/Controller/Factory/MyControllerFactory.php

namespace Foo\Controller\Factory; 

use ...; 

class MyControllerFactory implements FactoryInterface 
{ 

    public function createService(ServiceLocatorInterface $serviceLocator) 
    { 
     $fooPrototype = new Foo(); 
     $realServiceLocator = $serviceLocator->getServiceLocator(); 
     // $myForm = $realServiceLocator->get('Foo\Form\MyForm'); <-- This doesn't work correctly for this case. The FormElementManager should be used instead. 
     $formElementManager = $realServiceLocator->get('FormElementManager');       
     $myForm = $formElementManager->get('Foo\Form\MyForm'); 
     return new MyController($myForm, $fooPrototype); 
    } 
} 

回答

4

此問題是因爲您正在以表格__construct()方法添加表單元素,而不是init()as suggested in the documentation

您可以使用工廠而不是可調用的工具來處理元素/字段集/表單中的依賴關係。

現在是第一次接觸。

如果您是通過擴展Zend\Form\Form創建表單類,你不能在__construct -or添加自定義元素(如我們在這裏我們使用的自定義元素的FQCN在前面的例子已經完成),而是在init()方法:

原因是新形式的工廠(這是用來創建使用add()新元素)必須有應用程序的表單元素經理injected after the form's constructor has been called這個表單元素管理器實例包含您的自定義表單的所有引用根據form_elements conf註冊的元素配置密鑰。

致電add()的形式__constructthe form factory will lazy load a new instance of the form element manager;這將能夠創建所有默認的表單元素,但不會有任何關於您的自定義表單元素的知識。

+0

非常感謝您的詳細解答!我將構造函數的初始化邏輯移到了init()中。但它不起作用。對於**'Form' **,元素只是沒有被找到,例如:'沒有在form中找到[foo]的名字。對於**'FieldSet's **:與以前相同的錯誤:'Zend \ Form \ FormElementManager :: get無法爲Order \ Form \ Fieldset \ Foo獲取或創建一個實例。 – automatix

+0

我還分析了'init()'中'FormElementManager'的狀態。由於'init()'在構造函數之後被調用,所以我期望在MyFieldset-> factory-> formElementManager-> factories'中找到自定義字段集工廠。但該屬性只包含標準的Zend工廠。 – automatix

+0

@automatix您是否使用'formElementManager-> get('Order \ Form \ Fieldset \ Foo')創建* form *;'在'form_elements'中註冊了'Order \ Form \ Fieldset \ Foo'?你的問題只顯示'Storage \ Form \ Fieldset \ Foo'。 – AlexP

相關問題