如何在ZF2中的字段集工厂中使用集合


How to use collections in a fieldset factory in ZF2

我正在用ZF2和Doctrine开发一个项目。我正试图在本教程所示的形式创建中使用Doctrine Hydrator。在该方法中,在控制器中创建一个ObjectManager对象,并在实例化时将其传递给新表单。当我想使用ZF2的FormElementManager时,将ObjectManager对象从控制器传递到窗体会产生问题,因为ZF2要求我通过Zend''form''FormElementManager获得窗体类的实例,而不是直接实例化它。要解决此要求,我已经根据如何通过ZF2 FormElementManager将Doctrine ObjectManager传递给表单的问题的答案创建了表单和字段集工厂。问题答案中提供的方法适用于典型的字段集元素,但我需要确定如何包含集合元素。本教程在父字段集中的collection元素中使用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
        )
));