如何修复ZF2中的“在干草堆中找不到输入”?

时间:2019-11-22 09:28:05

标签: zend-framework2 zend-form zend-form-select

我的代码中有一个无法解决的问题。我正在使用Zend Framework 2.4,并且编写了一个表单,但是一旦对其进行验证,就会收到错误 在干草堆中找不到输入 。这是我收到错误的3个输入:

author_core

我以其他形式看到我应该放 $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' ) )); ,但这也不起作用。

3 个答案:

答案 0 :(得分:0)

当然不能用。

该消息来自\Zend\Validator\InArray,从本质上讲,它的意思是:“ 您的用户对您的选择进行了恶意处理,请注意”。

一个示例是具有两个选项的Select Preferred fruit,例如“ Banana”和“ Ananas”,但是用户“ hack”该选择并将值“ 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创建一个控制器插件,而不是将其作为每个控制器的依赖项,但这是一个不同的问题。

答案 1 :(得分:0)

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

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

这是我的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遇到了我的可怕的英语:)

答案 2 :(得分:-1)

好的,我刚刚找到了解决方案,这是代码:

        $this->add(array(
        'name' => 'ACTIVITE1',
        'type' => 'Zend\Form\Element\Select',
        'required' => 'required',
        'options' => array(
            'value_options' => array(
                'Choisir l\'activité'
            ),
            'disable_inarray_validator' => true,
        ),
        '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' => true,
        ),
        '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' => true,
        ),
        'attributes' => array(
            'class' => 'form-control',
            'id' => 'select-session3'
        )
    ));