如何使用 Zend_Validate 两次

问题描述 投票:0回答:2

我正在使用 Zend_Validate_Db_NoRecordExists,我想根据数据库中的两个字段验证我的 Zend_Form,示例代码:

    $phone_1 = new Zend_Form_Element_Text('phone_1');
    $phone_1->addValidator(new Zend_Validate_Db_NoRecordExists(
                            array(
                                'field' => 'phone_1',
                                'table' => 'customer',
                    )))
            ->addValidator(new Zend_Validate_Db_NoRecordExists(
                            array(
                                'field' => 'phone_2',
                                'table' => 'customer',
                    )));

我能完成这个吗?

php zend-framework zend-form zend-db zend-validate
2个回答
2
投票

创建验证链

$chain = new Zend_Validate();
$foo   = new Zend_Validate_Db_NoRecordExists(...);
$bar   = new Zend_Validate_Db_NoRecordExists(...);
$chain->addValidator($foo)
      ->addValidator($bar);

$element->addValidator($chain); 

更新@Bob Kruithof

使用 ZF 1.12.3 快速而肮脏的样本。所有代码示例和行号均来自 ZF 1.12.3

<?php

$aPaths = array(
    'path/to/zf'
);

set_include_path(implode(PATH_SEPARATOR, $aPaths));

require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();

$element = new Zend_Form_Element_Text('testSO');

$chain = new Zend_Validate();
$bar = new Zend_Validate_Regex('/^Test/');
$baz = new Zend_Validate_Regex('/Valid$/');
$chain->addValidator($bar)
      ->addValidator($baz);

$element->addValidator($chain); 

echo PHP_VERSION . ', ' . Zend_Version::getLatest() . PHP_EOL;

var_dump($element->isValid('Test'));
var_dump($element->isValid('Valid'));
var_dump($element->isValid('Test Valid'));

/* output
5.3.8, 1.12.3
bool(false)
bool(false)
bool(true)
*/

?>

为什么有效:

Zend_Form_Element.php
第1144 - 1168行通过
Zend_Validate
对象或字符串设置验证器。你是对的——如果验证器与名称一起使用,而不是作为链使用,那么结果就是只有一个验证器。但结果我们有:

$this->_validators[$name] = $validator;
/* debugger info:
    $name --> (string) Zend_Validate
    $validator --> Zend_Validate object {
  _validators => array(2) (
    [0] => array(2) (
      [instance] => Zend_Validate_Regex object {
      }
      [breakChainOnFailure] => (bool) false
    )
    [1] => array(2) (
      [instance] => Zend_Validate_Regex object {
      }
      [breakChainOnFailure] => (bool) false
    )
  )
  _messages => array(0)
  _errors => array(0)
  zfBreakChainOnFailure => (bool) false
}
*/

public function addValidator($validator, $breakChainOnFailure = false, $options = array())
    {
        if ($validator instanceof Zend_Validate_Interface) {
            $name = get_class($validator);

            if (!isset($validator->zfBreakChainOnFailure)) {
                $validator->zfBreakChainOnFailure = $breakChainOnFailure;
            }
        } elseif (is_string($validator)) {
            $name      = $validator;
            $validator = array(
                'validator' => $validator,
                'breakChainOnFailure' => $breakChainOnFailure,
                'options'             => $options,
            );
        } else {
            require_once 'Zend/Form/Exception.php';
            throw new Zend_Form_Exception('Invalid validator provided to addValidator; must be string or Zend_Validate_Interface');
        }


        $this->_validators[$name] = $validator;

        return $this;
    }

当我们调用

$element->isValid())
时,它会迭代链内的所有验证器 - 检查
Zend_Validate.php
,第 91-110 行:

public function isValid($value)
    {
        $this->_messages = array();
        $this->_errors   = array();
        $result = true;
        foreach ($this->_validators as $element) {
            $validator = $element['instance'];
            if ($validator->isValid($value)) {
                continue;
            }
            $result = false;
            $messages = $validator->getMessages();
            $this->_messages = array_merge($this->_messages, $messages);
            $this->_errors   = array_merge($this->_errors,   array_keys($messages));
            if ($element['breakChainOnFailure']) {
                break;
            }
        }
        return $result;
    }

$this->_validators
是我们的验证器数组:

array(2) (
  [0] => array(2) (
    [instance] => Zend_Validate_Regex object {
      _messageTemplates => array(3) (
      )
      _messageVariables => array(1) (
      )
      _pattern => (string) /^Test/
      _value => null
      _messages => array(0)
      _obscureValue => (bool) false
      _errors => array(0)
      _translator => null
      _translatorDisabled => (bool) false
    }
    [breakChainOnFailure] => (bool) false
  )
  [1] => array(2) (
    [instance] => Zend_Validate_Regex object...

1
投票

Zend 将使用验证器的类名作为键将验证器添加到数组中的表单元素中。这意味着,如果您想添加相同的验证器两次但具有不同的规范,则第二个验证器将覆盖第一个验证器。

完成添加相同验证器的最简单且稍微混乱的方法是扩展验证器,以便第二个验证器接收不同的类名:

class NewValidator extends Zend_Validate_Db_NoRecordExists { }

现在您可以使用验证器两次:

$phone_1->addValidator(new Zend_Validate_Db_NoRecordExists(
                        array(
                            'field' => 'phone_1',
                            'table' => 'customer',
                )))
        ->addValidator(new NewValidator(
                        array(
                            'field' => 'phone_2',
                            'table' => 'customer',
                )));

这就能解决问题,并且比创建自定义验证器要快得多。

© www.soinside.com 2019 - 2024. All rights reserved.