4

我正在尝试验证 Zend_Form ,它有几个可选字段,我希望至少填写其中一个。在我的情况下,我有手机、家庭和办公室电话号码,我希望至少提供其中一个。

我试图通过创建扩展 Zend_Validate_Abstract 的自定义验证器来通过验证上下文(如建议的here )来实现这一点。问题是,如果所有可选字段都为空,则它们会从 $context 表单中丢失(传递给验证器类),并且这种方式根本不会被验证。因此,如果您填写三个选项(移动、家庭、工作)中的任何一个或几个,它们都将被验证(这很好,但为此不需要自定义验证器),但如果您不填写任何一个,就会有无法强制客户填写至少一个字段(这是我的目标)。

这是我所拥有的:

1.我的表格

<?php

class Application_Form_Application extends Zend_Form {

  public function init() {
    $this->setName('application');

    // attach sub forms to main form
    $this->addSubForms(array(
      'application' => $this->application(),
      ...
    ));
  }

  private function application() {
    $application = new Zend_Form_SubForm();
    // custom phone validation
    $phone_validation = array('phone_mobile' => 'Mobile', 'phone_home' => 'Home', 'phone_work' => 'Work');
    // phone mobile
    $app['phone_mobile'] = new Zend_Form_Element_Text('phone_mobile');
    $app['phone_mobile']->setLabel('Mobile')
                        ->addFilter('StripTags')
                        ->addFilter('StringTrim')
                        ->addValidator('Regex', false, array('/^[0-9]{8}$/i'))
                        ->addValidator(new Application_Form_PhoneMobileHomeWork($phone_validation), false);
    // phone home
    $app['phone_home'] = new Zend_Form_Element_Text('phone_home');
    $app['phone_home']->setLabel('Home')
                      ->addFilter('StripTags')
                      ->addFilter('StringTrim')
                      ->addValidator('Regex', false, array('/^[0-9]{8}$/i'))
                      ->addValidator(new Application_Form_PhoneMobileHomeWork($phone_validation), false);
    // phone work
    $app['phone_work'] = new Zend_Form_Element_Text('phone_work');
    $app['phone_work']->setLabel('Work')
                      ->addFilter('StripTags')
                      ->addFilter('StringTrim')
                      ->addValidator('Regex', false, array('/^[0-9]{8}$/i'))
                      ->addValidator(new Application_Form_PhoneMobileHomeWork($phone_validation), false);
    $application->AddElements($app);
  }

}
?>

2.自定义验证器

<?php

class Application_Form_PhoneMobileHomeWork extends Zend_Validate_Abstract {

  const NOT_PRESENT = 'notPresent';

  protected $_messageTemplates = array(
    self::NOT_PRESENT => 'At least one contact phone shall be provided!'
  );

  protected $_listOfFields;

  public function __construct(array $listOfFields) {
    $this->_listOfFields = $listOfFields;
    var_dump($listOfFields);exit;
  }

  public function isValid($value, $context = null) {
    var_dump($context);exit;
    ...
  }
?>

验证器总是通过第一个转储($listOfFields),但如果我删除它,isValid() 永远不会被调用,除非某些数据被输入到某些电话字段(我们想要阻止)。

当我进一步检查时,我找到了通过将空字段传递给 $context 参数来扩展 Zend_Validate 类的解决方案,但如果有人知道,我希望有一个更好的解决方案。

简而言之 - 如何验证某个表单,强制用户至少填写几个可选字段中的一个?

4

2 回答 2

1

如果我理解正确,您希望您的表单元素不需要,但使用自定义验证器防止它们为空(除非其中一个不为空)?然后,为了不跳过验证链,您需要防止它们为空调setAllowEmpty(false)用每个元素中的方法。

最后,在您的自定义验证器中,您将拥有如下内容:

foreach ($this->_listOfFields as $field) {
    if (isset($context[$field]) AND $context[$field])
    {
        return true;
    }
}

此外,请确保您的元素不是必需的 ( setRequired(false))。

于 2012-04-16T09:24:11.093 回答
1

问题是如果填写任何字段,表单中不存在 multi_checkbox 元素,则不会对其进行验证。

一种解决方案如下:使用始终选中的隐藏选项并验证是否始终选中此选项。

于 2013-03-27T10:07:42.890 回答