1

我正在使用 Zend_Validate_Db_NoRecordExists,我想针对 DB 中的两个字段验证我的 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',
                    )));

我能做到这一点吗?

4

2 回答 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())它时,它会遍历链中的所有验证器 - check 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...
于 2014-01-27T14:04:41.920 回答
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',
                )));

这将起到作用,并且比创建自定义验证器要快得多。

于 2014-01-27T13:49:38.920 回答