zend framework 2/3 multicheckbox disable isEmpty errorMessage

时间:2018-03-30 15:52:41

标签: zend-framework2 zend-form zend-framework3 zend-validate

默认情况下,当没有选择任何选项时,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类中找到它的任何痕迹。

难道真的没有更好的方法吗?

1 个答案:

答案 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:没有办法通过元素的选项改变这种行为(再次:那是愚蠢的)。

无论如何,可以通过使用扩展multiheckbox的自定义元素来完成某些事情(这实际上是我已经在做的,出于其他原因):

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函数中指定所需的参数。

显然,如果你已经使用了多版本控制台的自定义版本,这个解决方案是有意义的,否则......做出自己的考虑。

UPDATE:处理元素的必需属性,实际使用

基本上你将以这种方式处理所需的属性(这里是一个自定义的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',
    [...]