在 Zend Framework 2 中渲染和处理相同的表单两次


Rendering and process same form twice in Zend Framework 2?

如果用户选中选择框,我需要再次呈现和处理相同的表单。我查看了表单集合,但它并没有完全解决我的问题,因为我不需要呈现一组字段,而是我的要求是再次呈现完整的表单。所以我添加了另一个函数 getClone($prefix) 来获取表单的克隆,该克隆在表单名称中添加前缀后返回表单对象的克隆。喜欢这个

<?php
namespace Company'Form;
use Zend'Form'Form;
use Zend'InputFilter'Factory as InputFactory;
use Zend'InputFilter'InputFilter;
use Zend'InputFilter'InputFilterAwareInterface;
use Zend'InputFilter'InputFilterInterface;
class CompanyAddress extends Form implements InputFilterAwareInterface {
    protected $inputFilter;
    public function __construct($countries, $name = 'null') {
        parent::__construct('company_address');
        $this->setAttribute('method', 'post');
        $this->setAttribute('id', 'company_address');
        $this->add(array(
            'name' => 'street_1',
            'attributes' => array(
                'id' => 'street_1',
                'type' => 'text',
            ),
            'options' => array(
                'label' => 'Street *',
            )
        ));
        $this->add(array(
            'name' => 'street_2',
            'attributes' => array(
                'id' => 'street_2',
                'type' => 'text',
            ),
            'options' => array(
                'label' => 'Street 2',
            )
        ));
        $this->add(array(
            'name' => 'country_id',
            'type' => 'Zend'Form'Element'Select',
            'attributes' => array(
                'id' => 'country_id',
            ),
            'options' => array(
                'label' => 'Country',
                'value_options' => $countries
            )
        ));
        $this->add(array(
            'name' => 'city_id',
            'type' => 'Zend'Form'Element'Select',
            'attributes' => array(
                'id' => 'city_id',
            ),
            'options' => array(
                'label' => 'City ',
                'value_options' => array()
            )
        ));

        $this->add(array(
            'name' => 'zip',
            'attributes' => array(
                'id' => 'zip',
                'type' => 'text',
            ),
            'options' => array(
                'label' => 'ZIP',
                'value_options' => array()
            )
        ));
        $this->add(array(
            'name' => 'address_type',
            'type' => 'Zend'Form'Element'Select',
            'attributes' => array(
                'id' => 'zip',
            ),
            'options' => array(
                'label' => 'Type',
                'value_options' => array(
                    '' => 'Select Type',
                    'default' => 'Default',
                    'invoice' => 'Invoice',
                    'both' => 'Both',
                )
            )
        ));
    }
    public function getClone($prefix){
        $form = clone $this;
        foreach($form->getElements() as $element){
            $name = $element->getName();
            $element->setName("$prefix[$name]");
        }
        return $form;
    }
    public function getInputFilter() {
        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();
            $factory = new InputFactory();
            $inputFilter->add($factory->createInput(array(
                        'name' => 'street_1',
                        'required' => true,
                        'filters' => array(
                            array('name' => 'StripTags'),
                            array('name' => 'StringTrim'),
                        ),
                        'validators' => array(
                            array(
                                'name' => 'NotEmpty',
                                'options' => array('message' => 'Street cannot be empty'),
                            ),
                        ),
                    )));
            $inputFilter->add($factory->createInput(array(
                        'name' => 'street_2',
                        'required' => false,
                        'filters' => array(
                            array('name' => 'StripTags'),
                            array('name' => 'StringTrim'),
                        ),
                        'validators' => array(
                        ),
                    )));
             $inputFilter->add($factory->createInput(array(
                        'name' => 'city_id',
                        'required' => true,
                        'filters' => array(
                            array('name' => 'StripTags'),
                            array('name' => 'StringTrim'),
                        ),
                        'validators' => array(
                            array(
                                'name' => 'NotEmpty',
                                'options' => array('message' => 'City cannot be empty'),
                            ),
                        ),
                    )));
             $inputFilter->add($factory->createInput(array(
                        'name' => 'country_id',
                        'required' => true,
                        'filters' => array(
                            array('name' => 'StripTags'),
                            array('name' => 'StringTrim'),
                        ),
                        'validators' => array(
                            array(
                                'name' => 'NotEmpty',
                                'options' => array('message' => 'Country cannot be empty'),
                            ),
                        ),
                    )));
             $inputFilter->add($factory->createInput(array(
                        'name' => 'zip',
                        'required' => true,
                        'filters' => array(
                            array('name' => 'StripTags'),
                            array('name' => 'StringTrim'),
                        ),
                        'validators' => array(
                            array(
                                'name' => 'NotEmpty',
                                'options' => array('message' => 'ZIP cannot be empty'),
                            ),
                        ),
                    )));
             $inputFilter->add($factory->createInput(array(
                        'name' => 'address_type',
                        'required' => true,
                        'filters' => array(
                            array('name' => 'StripTags'),
                            array('name' => 'StringTrim'),
                        ),
                        'validators' => array(
                            array(
                                'name' => 'NotEmpty',
                                'options' => array('message' => 'Address Type cannot be empty'),
                            ),
                        ),
                    )));

            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }
}

比在我的行动中,我这样做了

public function testAction() {
    $countries = $this->getServiceLocator()->get('Country')->getSelect();
    $companyAddressForm = new CompanyAddressForm($countries);
    $clone = $companyAddressForm->getClone('address2');
    if($this->request->isPost()){
        $data = $this->request->getPost();
        $companyAddressForm->setData($data);
        $clone->setData($data['address2']);
        $isFormOneValid = $companyAddressForm->isValid();
        //$isFormTwoValid = $clone->isValid();
    }
    $view = new ViewModel();
    $view->companyAddressForm = $companyAddressForm;
    $view->clone = $clone;
    return $view;
}

这正在按照我预期的工作,表单正在正确呈现和验证,我想知道这是正确的方法还是黑客?

如果两个窗体完全相同,则无需在控制器操作中声明和验证两个窗体。

原因:

如果有两个表单呈现您的 HTML 页面。用户一次只能发布其中一个表单,并且您一次只需要验证一个表单。您现在正在做的是再次使用相同的帖子数据验证相同的表单。因此,无论$isFormOneValid,$isFormTwoValid都是真的,要么都是假的。

相反,只声明一个表单,在视图中呈现两次,并在发布时使用发布数据对其进行验证。如果两种形式在属性、过滤器、验证器等方面不同,那么您可以创建两个方法,如 $form->applyForm1Validarots() 和 $form->applyForm2Validarots,检查 select 元素的值,并在调用 isValid() 之前调用适当的方法来应用 validaorts/过滤器。

希望我有帮助