我的代码中有一个无法解决的问题。我正在使用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'
)
));
,但这也不起作用。
答案 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'
)
));