默认情况下,当没有选择任何选项时,multiheckbox元素会触发错误消息:
array (size=1)
'checkbox' =>
array (size=1)
'isEmpty' => string 'Value is required and can't be empty' (length=36)
我发现可以使用函数getInputFilterSpecification
禁用该消息:
class MyForm extends Form implements InputFilterProviderInterface{
private $inputFilter;
public function __construct($name = null){
parent::__construct($name);
$this->add([
'name' => 'checkbox',
'type' => 'checkbox',
'attributes' => [],
'options' => [
'value_options' =>[
[
'value' => '0',
//'selected' => true,
'label' => 'One',
'label_attributes'=>[],
'attributes' => [],
],
[
'value' => '1',
'label' => 'Two',
'label_attributes'=>[],
'attributes' => [],
],
[
'value' => '2',
'label' => 'Three',
'label_attributes'=>[],
'attributes' => [],
],
],
],
]);
}//construct
public function getInputFilterSpecification() {
return array(
'checkbox'=>['required'=>false,],
);
}
}//class
这种方法唯一的“问题”是你必须为multiheckbox元素的所有实例指定名称和相对选项;有10个不同的多个盒子,输入过滤器的规格如下:
public function getInputFilterSpecification() {
return array(
'checkbox1'=>['required'=>false,],
'checkbox2'=>['required'=>false,],
'checkbox3'=>['required'=>false,],
...
);
}
...好吧它并没有那么糟糕,但它似乎相当愚蠢,因为元素(和/或所有值选项)接受属性required
,但实际上它被视为需要和完全没有意义。
该消息来自哪里?它似乎是一个预先指定的notEmpty验证器,但我没有在Zend的Mulicheckbox
类或父Checkbox
类中找到它的任何痕迹。
难道真的没有更好的方法吗?
答案 0 :(得分:1)
我自己找到了答案。
Zend的Multicheckbox元素扩展了实现InputProviderInterface
的Checkbox元素。
在Checkbox(第165行)中有:
public function getInputSpecification()
{
$spec = [
'name' => $this->getName(),
'required' => true,
];
if ($validator = $this->getValidator()) {
$spec['validators'] = [
$validator,
];
}
return $spec;
}
从Zend\InputFilter\Input
类检索该必需参数,如果为true(始终为true),则添加notEmpty验证器。
Ergo:没有办法通过元素的选项改变这种行为(再次:那是愚蠢的)。
namespace Form\Form\Element;
use Zend\InputFilter\InputProviderInterface;
use Zend\ModuleManager\Feature\ViewHelperProviderInterface;
use Zend\Form\Element\MultiCheckbox;
class BootstrapMultiCheckbox extends MultiCheckbox implements ViewHelperProviderInterface, InputProviderInterface{
protected $attributes = [
'type' => 'bootstrapMultiCheckbox',
];
public function getViewHelperConfig(){return array('Form\Form\View\Helper\BootstrapMultiCheckboxHelper', null);}
public function getInputSpecification(){
$spec = [
'name' => $this->getName(),
'required' => false,
];
if ($validator = $this->getValidator()) {
$spec['validators'] = [$validator,];
}
return $spec;
}
}
我刚刚复制了原始Checkbox元素中的getInputSpecification
函数,并将required设置为false。这样就不再需要在表单的getInputFilterSpecification
函数中指定所需的参数。
显然,如果你已经使用了多版本控制台的自定义版本,这个解决方案是有意义的,否则......做出自己的考虑。
基本上你将以这种方式处理所需的属性(这里是一个自定义的Radio元素):
//Form __construct:
$this->add([
'name' => 'radio',
'type' => BootstrapRadio::class,
'attributes' => ['required' => true,],
'options' => [
'value_options' =>[...],
],
]);
然后:
//BootstrapRadio Element:
public function getInputSpecification(){
//If required==true, then the notEmpty validator will be added (see above)
$required=$this->getAttribute('required');
$spec = [
'name' => $this->getName(),
'required' => $required,
];
if ($validator = $this->getValidator()) {
$spec['validators'] = [$validator,];
}
return $spec;
}
或者您可能只想将所需属性分配给几个选项(对无线电元素毫无意义):
//Form __construct:
$this->add([
'name' => 'checkbox',
'type' => BootstrapMultiCheckbox::class,
'options' => [
'value_options' =>[
[
'value' => '0',
'label' => 'One',
],
[
'value' => '1',
'label' => 'Two',
'attributes' => ['required' => true,],
],
[
'value' => '2',
'label' => 'Three',
'attributes' => ['required' => true,],
],
],
],
]);
然后:
//Custom element:
namespace Form\Form\Element;
use Zend\InputFilter\InputProviderInterface;
use Zend\ModuleManager\Feature\ViewHelperProviderInterface;
use Zend\Form\Element\MultiCheckbox;
use Zend\Validator\NotEmpty;
use Form\Form\Validator\BootstrapMulticheckboxValidator;
class BootstrapMultiCheckbox extends MultiCheckbox implements ViewHelperProviderInterface, InputProviderInterface{
protected $attributes = [
'type' => 'bootstrapMultiCheckbox',
];
protected $requiredValues=false;
public function getViewHelperConfig(){return array('Form\Form\View\Helper\BootstrapMultiCheckboxHelper', null);}
public function getInputSpecification(){
$required=$this->setIsRequired();
$spec = [
'name' => $this->getName(),
'required' => $required,
];
if ($validator = $this->getValidator()) {
$spec['validators'] = $this->requiredValues ? [$validator, new BootstrapMulticheckboxValidator($this->requiredValues)] : [$validator];
}
return $spec;
}
public function setIsRequired(){
$value=$this->getValue();
if(!$value && $this->getAttribute('required')){return true;}
foreach ($this->getValueOptions() as $key => $option){
if(isset($option['attributes']['required'])){$this->requiredValues[$key]=$option['value'];}
}
if(!$value && $this->requiredValues){return true;}
return false;
}
}
最后:
//custom validator
namespace Form\Form\Validator;
use Traversable;
use Zend\Stdlib\ArrayUtils;
use Zend\Validator\AbstractValidator;
use Zend\Validator\NotEmpty;
class BootstrapMulticheckboxValidator extends AbstractValidator
{
const IS_EMPTY = 'isEmpty';
protected $requiredValues;
protected $messageTemplates = [
self::IS_EMPTY => 'Value is required and can\'t be empty',
];
public function __construct($requiredValues)
{
$this->requiredValues=$requiredValues;
parent::__construct(null);
}
public function isValid($values)
{
foreach($this->requiredValues as $required){
if(!in_array($required, $values)){
$this->error(self::IS_EMPTY);
return false;
}
}
return true;
}
}
注意:取决于您呈现自定义元素的方式,您可能希望通过向表单添加novalidate属性来禁用浏览器验证:
class BootstrapForm extends Form implements InputFilterProviderInterface{
private $inputFilter;
public function __construct($name = null){
parent::__construct($name);
$this->setAttribute('novalidate',true);
$this->add([
'name' => 'checkbox',
[...]