0

我的代码中有一个我无法解决的问题。我正在使用 Zend 框架 2.4 并且我编写了一个表单,但是一旦我验证它,我就会收到错误The input was not found in the haystack。这是我收到错误的 3 个输入:

 $this->add(array(
        'name' => 'ACTIVITE1',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            ),
            'disable_inarray_validator' => false,
        ),
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session1'
        )
    ));

    $this->add(array(
        'name' => 'ACTIVITE2',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            )
        ),
        'disable_inarray_validator' => false,
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session2'
        )
    ));

    $this->add(array(
        'name' => 'ACTIVITE3',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            )
        ),
        'disable_inarray_validator' => false,
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session3'
        )
    ));

我看到了我应该输入的其他形式,'disable_inarray_validator' => false但这也不起作用。

4

2 回答 2

0

当然它不起作用。

该消息来自\Zend\Validator\InArray本质上,它的意思是:“您的用户正在对您的选择进行一些骇人听闻的事情,请注意”。

一个示例是具有两个选项的 Select Preferred fruit,例如“Banana”和“Ananas”,但用户“破解”该选择并将值“Audi”发送到服务器。验证器InArray非常重要,不应该被禁用(好吧,只有在少数例外情况下......)。

现在,您为什么会收到此错误?答案是...您没有告诉选择选项是什么。您创建了一个 Select,但没有指定它的选项。您将标签/占位符放在选项的位置。正确的选择是:

$this->add(array(
    'name' => 'ACTIVITE1',
    'type' => 'Zend\Form\Element\Select',
    'required' => 'required',
    'options' => array(
        'value_options' => array(
            1 => 'Fitness',
            2 => 'Parcour',
            3 => 'Velo',
            4 => 'Tapis roulant',
            // ... and so on
        )
    ),
    'attributes' => array(
        'class' => 'form-control',
        'id' => 'select-session1',
        'placeholder' => "Choisir l'activité"
    )
));

什么是“奇怪”的事实是你在一个空的选择中填充了一些东西,那么我的问题是:为什么?

选择(通常)用于预定义的值列表。如果您想允许您的用户填写自定义文本,那么您应该考虑Text使用自动完成选项创建一个字段。

编辑:从数据库中选择值

如果您想创建一个包含来自数据库的选项列表的选择,则该路线有点复杂,但是一旦您学会了如何去做,它就会变得容易得多。

请注意:这不是“复制和粘贴解决方案”。由于我无法访问您的代码,因此我正在编造名称(类、命名空间、方法、变量)只是为了创建一个完整的示例 :)

首先,您必须创建一个自定义元素。在这种情况下,它将是一个自定义选择:

namespace Yournamespace;

use Zend\Form\Element\Select;
use Yournamespace\ActivityMapper;

class ActivitySelect extends Select {

    protected $activityMapper;

    public function __construct(ActivityMapper $activityMapper, $name = null, $options = []) {
        parent::__construct($name, $options);
        $this->activityMapper = $activityMapper;
    }

    public function init() {
        $valueOptions = [];
        foreach ($this->activityMapper->fetchAll() as $activity) {
            $valueOptions[$activity->getActivityId()] = $activity->getActivityName();
        }
        $this->setValueOptions($valueOptions);
    }

}

这里真正重要的是您必须在方法中实例化您的元素(选项、类等..)init

由于此元素具有依赖项 ( ActivityMapper),因此您必须为此元素创建一个工厂:

namespace Yournamespace;

use Zend\ServiceManager\Factory\FactoryInterface;
use \Interop\Container\ContainerInterface;

class ActivitySelectFactory implements FactoryInterface {

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null): object {
        $activityMapper = $container->get(\Yournamespace\ActivityMapper::class);
        return \Yournamespace\ActivitySelect($activityMapper);
    }

}

这个工厂必须添加到配置中,更准确地说,在里面module.config.php

return [
    // ...
    'form_elements' => [
        'factories' => [
            \Yournamespace\ActivitySelect::class => \Yournamespace\ActivitySelectFactory::class,
        ]
    ]
    // ...
];

现在,您也必须修改表单。所有元素都必须添加到init方法内部,而不是构造函数内部:

namespace Yournamespace;

use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;

class ActivityForm extends Form implements InputFilterProviderInterface {

    public function init() {
        parent::init();

        // ...
        $this->add([
            'name' => 'ACTIVITE1',
            'type' => \Yournamespace\ActivitySelect::class,
            'attributes' => [
                'class' => 'form-control',
                'id' => 'select-session1',
                'required' => true, // This will work only clientside, don't forget the inputfilter!
                'placeholder' => 'Choisir l\'activité',
            ],
            'options' => [
                'label' => 'Choisir l\'activité',
            ]
        ]);
        // ...

    }

    public function getInputFilterSpecification() {
        // ...
        $inputFilter[] = [
            'name' => 'ACTIVITE1',
            'required' => true
        ];
        // ...
        return $inputFilter;
    }

}

最后,您还必须修改控制器,因为您需要从以下位置检索表单FormElementManager

namespace Yournamespace;

use Zend\Form\FormElementManager;

class YourController extends AbstractActionController {
    private $formManager;

    public function __construct(FormElementManager $formManager) {
        $this->formManager = $formManager;
    }

    public function choisirActiviteAction(){
        // ...
        $form = $this->formManager->get(\Yournamespace\ActivityForm::class);
        // ...
    }
}

下一个不错的步骤是为$formManager.

于 2019-11-25T15:07:10.657 回答
0

感谢您的回答!我明白你的意思,但我这样做是因为我不想控制选择,因为我无法控制所有可能的选项。

因为选项来自数据库,所以我让他们执行 AJAX 请求,然后将所有选项添加到视图中的选择中。因此,选项可能会有所不同,并且不是固定的。

这是我的 AJAX 请求:

$("#input-dtNaissance").change(function() {
        $.when($(".activites-options").remove()).then(function() {
            if ($("#input-dtNaissance").val() != " ") {
                //on supprime les anciennes activités proposées au cas où il y en ai
                var year = $("#input-dtNaissance").val().substring(0,4);
                if (year == "") {
                    year = 1;
                }
                // si date supprimée/réinitialisée 
                if (year == 1) {
                    // on supprime les activités proposées du select
                    $(".activites-options").remove();
                } else {
                    $.getJSON("http://localhost/ecoleMunicipalSport/app/public/activite/listActivitySession1/" + year, function(data) {
                        data.forEach(element => {
                            var option = "<option value='" + element.ID_ACTIVITES + "' class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
                            $("#select-session1").append(option);
                        });
                    });
                    $.getJSON("http://localhost/ecoleMunicipalSport/app/public/activite/listActivitySession2/" + year, function(data) {
                        data.forEach(element => {
                            var option = "<option value='" + element.ID_ACTIVITES + "'class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
                            $("#select-session2").append(option);
                        });
                    });
                    $.getJSON("http://localhost/ecoleMunicipalSport/app/public/activite/listActivitySession3/" + year, function(data) {
                        data.forEach(element => {
                            var option = "<option value='" + element.ID_ACTIVITES + "' class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
                            $("#select-session3").append(option);
                        });
                    });
                }
            }
        });
    })

我知道这不是很安全,如果您有更好的解决方案,更安全,我愿意接受这些建议。

晚上好。

PS:Sorree faur my terribl anglish :)

于 2019-11-25T16:23:10.007 回答