单选按钮:在大海捞针中找不到输入?

Radio button: input was not found in the haystack?

每当我提交表单时,我都会收到此消息:

The input was not found in the haystack.

这是针对 shipping-method 元素(单选按钮)的。无法弄清楚这是什么意思,该元素的 POST 数据不为空。

public function getInputFilter()
{
    if (!$this->inputFilter) {
        $inputFilter = new InputFilter();

        // Some other basic filters

        $inputFilter->add(array(
                'name' => 'shipping-method',
                'required' => true,
                'filters' => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim')
                ),
                'validators' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'max' => 20,
                        ),
                    ),
                    array(
                        'name' => 'Db\RecordExists',
                        'options' => array(
                            'table' => 'shipping',
                            'field' => 'shipping_method',
                            'adapter' => $this->dbAdapter
                        )
                    ),
                ),
        ));

        $inputFilter->get('shipping-address-2')->setRequired(false);
        $inputFilter->get('shipping-address-3')->setRequired(false);

        $this->inputFilter = $inputFilter;
    }

    return $this->inputFilter;
}

我一直在寻找 <select> 的解决方案。

这是示例 POST 数据:

object(Zend\Stdlib\Parameters)#143 (1) {
  ["storage":"ArrayObject":private] => array(9) {
    ["shipping-name"] => string(4) "TEST"
    ["shipping-address-1"] => string(4) "test"
    ["shipping-address-2"] => string(0) ""
    ["shipping-address-3"] => string(0) ""
    ["shipping-city"] => string(4) "TEST"
    ["shipping-state"] => string(4) "TEST"
    ["shipping-country"] => string(4) "TEST"
    ["shipping-method"] => string(6) "Ground"
    ["submit-cart-shipping"] => string(0) ""
  }
}

更新: form.phtml

<div class="form-group">
    <?= $this->formRow($form->get('shipping-method')); ?>
    <?= $this->formRadio($form->get('shipping-method')
            ->setValueOptions(array(
                'Ground' => 'Ground',
                'Expedited' => 'Expedited'))
            ->setDisableInArrayValidator(true)); ?>
</div>

ShippingForm.php

    $this->add(array(
        'name' => 'shipping-method',
        'type' => 'Zend\Form\Element\Radio',
        'options' => array(
            'label' => 'Shipping Method',
            'label_attributes' => array(
                'class' => 'lbl-shipping-method'
            ),
        )
    ));

昨天刚发生过这件事。

select 和 multi select ZF2+ 元素有一个内置的 in_array 验证器。

记住过滤器出现在验证器之前。

您可能在这里做的太多了——在 ZF2 表单中很少需要过滤或添加验证器 ot select 和多个 select 表单元素。内置的元素验证器非常强大,ZF 为我们做了很多工作。

尝试删除元素的过滤器和验证器,例如:

$inputFilter->add(array(
            'name' => 'shipping-method',
            'required' => true,
    ));

我还看到了另一种极端情况:在控制器(或视图)中的某处更改 select 元素的 valueOptions,导致在视图和表单验证中使用不同的 valueOptions(在我们的例子中,它替换了元素与验证前的新元素)。

我认为你的问题在于你在设置 InArray 验证器之后添加你的值选项,因此验证器没有大海捞针。

试试这个

$this->add(array(
    'name' => 'shipping-method',
    'type' => 'Zend\Form\Element\Radio',
    'options' => array(
        'label' => 'Shipping Method',
        'label_attributes' => array(
            'class' => 'lbl-shipping-method'
        ),
        'value_options' => array(
            'Ground' => 'Ground',
            'Expedited' => 'Expedited'
        ),
        'disable_inarray_validator' => TRUE,
    )
));

并从您的视图中删除 setValueOptions 和 setDisableInArrayValidator。

希望这有效。

问题出在您使用 setValueOptions()setDisableInArrayValidator() 时。您应该在您的代码中更早地执行此操作,因为它在验证您的表单之前从未设置过,因此 inputfilter 仍然包含默认值作为 InArray 验证器。在检查输入过滤器的验证之后,您可以为 shipping_methods.

设置不同的选项

您应该将 setValueOptions()setDisableInArrayValidator() 移到 $form->isValid() 之前。通过在表单本身中设置正确的选项或在控制器中执行此操作。最好的方法是将所有选项都放在一个地方,并在 class.

表格内进行
$this->add([
    'name' => 'shipping-method',
    'type' => 'Zend\Form\Element\Radio',
    'options' => [
        'value_options' => [
            'Ground'    => 'Ground',
            'Expedited' => 'Expedited'
        ],
        'disable_inarray_validator' => true,
        'label' => 'Shipping Method',
        'label_attributes' => [
            'class' => 'lbl-shipping-method',
        ],
    ],
]);

您可能想要更改的另一个小细节是设置值选项。它们现在是硬编码的,但您的输入过滤器正在检查数据库记录是否存在。使用数据库记录填充值选项。如果代码仍然包含旧方法但数据库有一些新方法,则它们不同步。

class ShippingForm extends Form
{
    private $dbAdapter;

    public function __construct(AdapterInterface $dbAdapter, $name = 'shipping-form', $options = [])
    {
        parent::__construct($name, $options)
        // inject the databaseAdapter into your form
        $this->dbAdapter = $dbAdapter;
    }

    public function init()
    {
        // adding form elements to the form
        // we use the init method to add form elements as from this point
        // we also have access to custom form elements which the constructor doesn't

        $this->add([
            'name' => 'shipping-method',
            'type' => 'Zend\Form\Element\Radio',
            'options' => [
                'value_options' => $this->getDbValueOptions(),
                'disable_inarray_validator' => true,
                'label' => 'Shipping Method',
                'label_attributes' => [
                    'class' => 'lbl-shipping-method',
                ],
            ],
        ]);
    }

    private function getDbValueOptions()
    {
        $statement = $this->dbAdapter->query('SELECT shipping_method FROM shipping');
        $rows = $statement->execute();

        $valueOptions = [];

        foreach ($rows as $row) {
            $valueOptions[$row['shipping_method']] = $row['shipping_method'];
        }

        return $valueOptions;
    }
}