Как использовать коллекции на фабрике fieldset в ZF2

Я разрабатываю проект с ZF2 и Doctrine. Я пытаюсь использовать Doctrine Hydrator в создании формы, как показано в этом уроке . В этом методе объект ObjectManager создается в контроллере и передается в новую форму при его создании. Передача объекта ObjectManager из контроллера в форму создает проблему, когда я хочу использовать FormElementManager ZF2, потому что ZF2 требует, чтобы я получал экземпляр класса формы через Zend \ Form \ FormElementManager вместо прямого его создания. Чтобы обойти это требование, я создал фабрики форм и полей, основанные на ответе на вопрос « Как передать ObjectManager Doctrine в форму через ZF2 FormElementManager» . Метод, представленный в ответе на вопрос, работает для типичных элементов fieldset, но мне нужно определить, как включить элемент коллекции. Учебник использует объект ObjectManager в элементе коллекции в родительском наборе полей, и мне нужно выяснить, как добавить коллекцию с использованием фабрики.

TagFieldset из учебника, которое я пытаюсь подражать:

namespace Application\Form; use Application\Entity\Tag; use Doctrine\Common\Persistence\ObjectManager; use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; class TagFieldset extends Fieldset implements InputFilterProviderInterface { public function __construct(ObjectManager $objectManager) { parent::__construct('tag'); $this->setHydrator(new DoctrineHydrator($objectManager)) ->setObject(new Tag()); $this->add(array( 'type' => 'Zend\Form\Element\Hidden', 'name' => 'id' )); $this->add(array( 'type' => 'Zend\Form\Element\Text', 'name' => 'name', 'options' => array( 'label' => 'Tag' ) )); } public function getInputFilterSpecification() { return array( 'id' => array( 'required' => false ), 'name' => array( 'required' => true ) ); } } 

новый TagFieldsetFactory:

 namespace Application\Form; use Zend\Form\Fieldset; use Application\Entity\Tag; class TagFieldsetFactory { public function __invoke($formElementManager, $name, $requestedName) { $serviceManager = $formElementManager->getServiceLocator(); $hydrator = $serviceManager->get('HydratorManager')->get('DoctrineEntityHydrator'); $fieldset = new Fieldset('tags'); $fieldset->setHydrator($hydrator); $fieldset->setObject(new Tag); //... add fieldset elements. $fieldset->add(['...']); //... return $fieldset; } } 

BlogPostFieldset из учебника, который я пытаюсь подражать:

 namespace Application\Form; use Application\Entity\BlogPost; use Doctrine\Common\Persistence\ObjectManager; use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator; use Zend\Form\Fieldset; use Zend\InputFilter\InputFilterProviderInterface; class BlogPostFieldset extends Fieldset implements InputFilterProviderInterface { public function __construct(ObjectManager $objectManager) { parent::__construct('blog-post'); $this->setHydrator(new DoctrineHydrator($objectManager)) ->setObject(new BlogPost()); $this->add(array( 'type' => 'Zend\Form\Element\Text', 'name' => 'title' )); $tagFieldset = new TagFieldset($objectManager); $this->add(array( 'type' => 'Zend\Form\Element\Collection', 'name' => 'tags', 'options' => array( 'count' => 2, 'target_element' => $tagFieldset ) )); } public function getInputFilterSpecification() { return array( 'title' => array( 'required' => true ), ); } } 

новый BlogPostFieldsetFactory:

 namespace Application\Form; use Zend\Form\Fieldset; use Application\Entity\BlogPost; class BlogPostFieldsetFactory { public function __invoke($formElementManager, $name, $requestedName) { $serviceManager = $formElementManager->getServiceLocator(); $hydrator = $serviceManager->get('HydratorManager')->get('DoctrineEntityHydrator'); $fieldset = new Fieldset('blog_post'); $fieldset->setHydrator($hydrator); $fieldset->setObject(new BlogPost); //... add fieldset elements. $fieldset->add(['...']); //... return $fieldset; } } 

в module.config.php:

 'form_elements' => [ 'factories' => [ 'UpdateBlogPostForm' => 'Application\Form\UpdateBlogPostFormFactory', 'BlogPostFieldset' => 'Application\Form\BlogPostFieldsetFactory', 'TagFieldset' => 'Application\Form\TagFieldsetFactory', ], ], 

Когда я добавляю элементы набора полей В моем новом BlogPostFieldsetFactory я заменяю этот код из исходного набора полей:

 $this->add(array( 'type' => 'Zend\Form\Element\Text', 'name' => 'title' )); 

с этим:

 $fieldset->add(array( 'type' => 'Zend\Form\Element\Text', 'name' => 'title' )); 

Как заменить элемент коллекции из исходного набора полей:

 $tagFieldset = new TagFieldset($objectManager); $this->add(array( 'type' => 'Zend\Form\Element\Collection', 'name' => 'tags', 'options' => array( 'count' => 2, 'target_element' => $tagFieldset ) )); 

возможно, я задаю ваш вопрос неправильно …. но если вы заменили это

 $this->add(array( 'type' => 'Zend\Form\Element\Text', 'name' => 'title' )); 

с этим:

 $fieldset->add(array( 'type' => 'Zend\Form\Element\Text', 'name' => 'title' )); 

то вы, вероятно, можете заменить это:

 $tagFieldset = new TagFieldset($objectManager); $this->add(array( 'type' => 'Zend\Form\Element\Collection', 'name' => 'tags', 'options' => array( 'count' => 2, 'target_element' => $tagFieldset ) )); 

с этим:

 $tagFieldset = new TagFieldset($objectManager); $fieldset->add(array( 'type' => 'Zend\Form\Element\Collection', 'name' => 'tags', 'options' => array( 'count' => 2, 'target_element' => $tagFieldset ) )); 

теперь, если вы не можете передать объект $ objectManger в форму … хорошо, если вы посмотрите на код, у вас есть эта вещь, доступная $ serviceManager, эта вещь выглядит как контейнер DI, я уверен, что вы можете получить экземпляр $ objectManager оттуда, и если он недоступен, вы можете, вероятно, поместить его экземпляр внутри.

Таким образом, окончательный код, вероятно, заканчивается, выглядит так:

 $objectManager = $serviceManager->get('DoctrineObjectManager') //or something like this $tagFieldset = new TagFieldset($objectManager); $fieldset->add(array( 'type' => 'Zend\Form\Element\Collection', 'name' => 'tags', 'options' => array( 'count' => 2, 'target_element' => $tagFieldset ) ));