使用Zend Framework验证多个可选表单字段

4
我正在尝试验证Zend_Form,其中包含几个可选字段,我希望至少填写其中一个。在我的情况下,我有手机、家庭和办公电话号码,我希望至少提供其中一个。
我尝试通过验证上下文(如此处所建议的)来实现这一点,创建了扩展Zend_Validate_Abstract的自定义验证器。问题是,如果所有可选字段都为空,则它们将缺失表单$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类以解决此问题,但如果有人知道更好的解决方案,我希望能得到更好的解决方案。
简而言之,如何验证特定表单,强制用户填写多个可选字段中的至少一个?
2个回答

1
问题在于,如果任何一个字段被填充,多选框元素将不存在于表单中,然后它将无法得到验证。
一个解决方案是: 始终使用一个隐藏的选项并验证该选项始终被选中且选择了其他选项之一。

1
如果我理解正确,您希望您的表单元素不是必填项,但使用自定义验证器防止它们为空(除非其中一个不为空)?那么,为了不跳过验证链,您需要在每个元素中调用方法setAllowEmpty(false)来防止它们为空。
最后,在您的自定义验证器中,您将有类似以下内容的代码:
foreach ($this->_listOfFields as $field) {
    if (isset($context[$field]) AND $context[$field])
    {
        return true;
    }
}

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

setAllowEmpty(false)确实强制通过验证链,但这并不总是需要的,例如如果您有其他验证,它们将被触发,从而迫使客户填写每个字段。但一般来说,您的建议需要验证自定义规则,这回答了我的问题。请注意,我是Zend Framework的新手。感谢提示,我想我可以从那里处理。 - gogh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接