$form->isValid显示表单无效,但我的表单没有显示任何错误消息 - Zend Framework 2

8

在我的 CRUD 应用程序中,我在 addAction 中遇到了问题。在控制器上,逻辑未通过 $form->isValid() 验证,但表单没有显示任何错误消息。

我尝试使用以下代码(感谢Sam):

foreach($form->get('product')->getElements() as $el)
{
    echo $el->getName()." = ".$el->getValue()." > ".$el->getMessages()." <br/>";
}

这只显示字段的名称和值,但不包括错误消息。

我尝试让表单完全为空,它会触发“值是必需的,不能为空”错误消息,但是,然后,我逐个填写每个字段,直到我不再收到更多的错误消息,但表单仍然无效。

我的表单有一个产品Fieldset作为基本Fieldset和一个提交按钮。在Product Fieldset中,我有一个ID字段、一个名称字段、一个价格字段和一个品牌Fieldset。在我的品牌Fieldset内,我有一个id字段。像这样:

ProductForm:

class ProductForm extends Form
{

    public function init()
    {
        // we want to ignore the name passed
        parent::__construct('product');
        $this->setName('product');
        $this->setAttribute('method', 'post');

        $this->add(array(
               'name' => 'product',
                'type' => 'Administrador\Form\ProductFieldset',
                'options' => array(
                        'use_as_base_fieldset' => true
                ),
        ));
        $this->add(array(
                'name' => 'submit',
                'type' => 'Submit',
                'attributes' => array(
                        'value' => 'Add',
                        'id' => 'submitbutton',
                ),
        ));
    }
}

产品字段集:

class ProductFieldset extends Fieldset implements ServiceLocatorAwareInterface
{

    protected $serviceLocator;

    function __construct($name = null)
    {
        parent::__construct('product_fieldset');

        $this->setHydrator(new ArraySerializableHydrator());
        $this->setObject(new Product());
    }

    public function init()
    {

        $this->add(array(
                'name' => 'id',
                'type' => 'Hidden',
        ));
        $this->add(array(
                'name' => 'name',
                'type' => 'Text',
                'options' => array(
                        'label' => 'Name',
                ),
        ));
        $this->add(array(
                'name' => 'price',
                'type' => 'Text',
                'options' => array(
                        'label' => 'Price',
                ),
        ));
        $this->add(array(
                'name' => 'brand',
                'type' => 'BrandFieldset',
        ));
    }


    public function setServiceLocator(ServiceLocatorInterface $sl)
    {
        $this->serviceLocator = $sl;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }
}

品牌字段集:

class BrandFieldset extends Fieldset
{
    function __construct(BrandTable $brandTable)
    {
        parent::__construct('brand_fieldset');

        //$this->setHydrator(new ClassMethodsHydrator(false))->setObject(new Brand());

        $this->setHydrator(new ArraySerializableHydrator());
        $this->setObject(new Brand());

        $brandSelectOptionsArray = $brandTable->populateSelectBrand();
        $this->add(array(
                'name' => 'id',
                'type' => 'Select',
                'options' => array(
                        'label' => 'Brand',
                        'empty_option' => 'Please select a brand',
                        'value_options' => $brandSelectOptionsArray,
                ),
        ));
    }
}

这是我在addAction中的新表单语句:
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('Administrador\Form\ProductForm');

在我的“产品”模型中,我有输入筛选器,“id”字段需要的筛选器,以及“名称”字段需要的筛选器。并且对于品牌字段,我创建了另一个输入筛选器,并将其添加到主要的输入筛选器中。
$brandFilter->add($factory->createInput(array(
'name'     => 'id',
'required' => true,
'filters'  => array(
    array('name' => 'Int'),
),
)));
$inputFilter->add($brandFilter, 'brand');

奇怪的行为是,我的editAction正常工作并具有相同的逻辑。

是否有一种形式的从表单中回显内部错误消息的方法,帮助我理解为什么表单无效。

编辑 2013-06-01

这是我的完整控制器:

class ProductController extends AbstractActionController
{

    protected $productTable;
    protected $brandTable;

    public function indexAction()
    {
        return new ViewModel(array(
            'products' => $this->getProductTable()->fetchAll(),
        ));
    }

    public function addAction()
    {
        $formManager = $this->serviceLocator->get('FormElementManager');
        $form = $formManager->get('Administrador\Form\ProductForm');
        $form->get('submit')->setValue('Add');

        $request = $this->getRequest();
        if ($request->isPost()) {
            $product = new Product();
            $product->brand = new Brand();
            $form->setInputFilter($product->getInputFilter());
            $form->setData($request->getPost());

            if ($form->isValid()) {
                $product->exchangeArray($form->getData());
                $this->getProductTable()->saveProduct($product);

                // Redirect to list of products
                return $this->redirect()->toRoute('product');
            }
        }
        return new ViewModel(array(
            'form' => $form,
        ));
    }

    public function editAction()
    {
        $id = (int) $this->params()->fromRoute('id', 0);
        if (!$id) {
            return $this->redirect()->toRoute('product', array(
                    'action' => 'add'
            ));
        }

        // Get the Product with the specified id.  An exception is thrown
        // if it cannot be found, in which case go to the index page.
        try {
            $product = $this->getProductTable()->getProduct($id);
        }
        catch (\Exception $ex) {
            return $this->redirect()->toRoute('product', array(
                    'action' => 'index'
            ));
        }
        $formManager = $this->serviceLocator->get('FormElementManager');
        $form = $formManager->get('Administrador\Form\ProductForm');
        $brand = $this->getBrandTable()->getBrand($product->brand);
        $product->brand = $brand;
        $form->bind($product);
        $form->get('submit')->setAttribute('value', 'Edit');

        $request = $this->getRequest();
        if ($request->isPost()) {
            $form->setInputFilter($product->getInputFilter());
            $form->setData($request->getPost());

            if ($form->isValid()) {
                $this->getProductTable()->saveProduct($form->getData());

                // Redirect to list of products
                return $this->redirect()->toRoute('product');
            }
        }

        return array(
                'id' => $id,
                'form' => $form,
        );
    }

    public function deleteAction()
    {
        $id = (int) $this->params()->fromRoute('id', 0);
        if (!$id) {
            return $this->redirect()->toRoute('product');
        }

        $request = $this->getRequest();
        if ($request->isPost()) {
            $del = $request->getPost('del', 'No');

            if ($del == 'Yes') {
                $id = (int) $request->getPost('id');
                $this->getProductTable()->deleteProduct($id);
            }

            // Redirect to list of products
            return $this->redirect()->toRoute('product');
        }

        return array(
                'id'    => $id,
                'product' => $this->getProductTable()->getProduct($id)
        );
    }


    public function getProductTable()
    {
        if (!$this->productTable) {
            $sm = $this->getServiceLocator();
            $this->productTable = $sm->get('Administrador\Model\ProductTable');
        }
        return $this->productTable;
    }

    public function getBrandTable()
    {
        if (!$this->brandTable) {
            $sm = $this->getServiceLocator();
            $this->brandTable = $sm->get('Administrador\Model\BrandTable');
        }
        return $this->brandTable;
    }
}

请提供涉及的完整控制器方法。 - netiul
好的,我会提供控制器的添加和编辑操作。 - Anel Gonzalez
3个回答

1
我的情况是我通过了错误的输入过滤器。isValid返回false,但$form->getMessages()为空。表单OrderForm具有以下内容:
$form->setInputFilter(new \Application\Form\UserInputFilter($er));

当我将UserInputFilter更改为OrderInputFilter时,它可以正常工作。

0

好的,我得到了答案 :D

这就是addAction应该是这样的:

public function addAction()
{
    $formManager = $this->serviceLocator->get('FormElementManager');
    $form = $formManager->get('Administrador\Form\ProductForm');
    $form->get('submit')->setValue('Add');

    $product = new Product();
    $product->brand = new Brand();

    $form->bind($product);  // I need to bind the product to the form to pass the isValid() validation

    $request = $this->getRequest();
    if ($request->isPost()) {
        $form->setInputFilter($product->getInputFilter());
        $form->setData($request->getPost());

        if ($form->isValid()) {
            $product = $form->getData();
            $this->getProductTable()->saveProduct($product);

            // Redirect to list of products
            return $this->redirect()->toRoute('product');
        }
    }
    return new ViewModel(array(
        'form' => $form,
    ));
}

显然,我需要将一个空的产品对象绑定到表单中,以便能够通过isValid()验证。之后,我从$form->getData()中检索一个产品对象。


0

你还可以这样做:$form->setBindOnValidate(false);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接