Zend表单验证器: 元素A或元素B

13

我在Zend表单中有两个字段,我想应用验证规则以确保用户只需输入其中一个字段。

    $companyname = new Zend_Form_Element_Text('companyname');
    $companyname->setLabel('Company Name');
    $companyname->setDecorators($decors);
    $this->addElement($companyname);

    $companyother = new Zend_Form_Element_Text('companyother');
    $companyother->setLabel('Company Other');
    $companyother->setDecorators($decors);
    $this->addElement($companyother);

我如何添加一个验证器,可以同时检查两个字段?

4个回答

12
请参见page上的“注意:验证上下文”。Zend_Form将上下文作为第二个参数传递给每个Zend_Form_Element::isValid调用。因此,只需编写自己的验证器来分析上下文即可。 编辑:
好吧,我想我会自己尝试一下。它没有经过测试,也不是全部解决方案,但它将为您提供基本思路。
class My_Validator_OneFieldShouldBePresent extend Zend_Validator_Abstract
{
    const NOT_PRESENT = 'notPresent';

    protected $_messageTemplates = array(
        self::NOT_PRESENT => 'Field %field% is not present'
    );

    protected $_messageVariables = array(
        'field' => '_field'
    );

    protected $_field;

    protected $_listOfFields;

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

    public function isValid( $value, $context = null )
    {
        if( !is_array( $context ) )
        {
            $this->_error( self::NOT_PRESENT );

            return false;
        }

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

        $this->_field = $field;
        $this->_error( self::NOT_PRESENT );

        return false;
    }
}

使用方法:

$oneOfTheseFieldsShouldBePresent = array( 'companyname', 'companyother' );

$companyname = new Zend_Form_Element_Text('companyname');
$companyname->setLabel('Company Name');
$companyname->setDecorators($decors);
$companyname->addValidator( new My_Validator_OneFieldShouldBePresent( $oneOfTheseFieldsShouldBePresent ) );
$this->addElement($companyname);

$companyother = new Zend_Form_Element_Text('companyother');
$companyother->setLabel('Company Other');
$companyother->setDecorators($decors);
$companyname->addValidator( new My_Validator_OneFieldShouldBePresent( $oneOfTheseFieldsShouldBePresent ) );
$this->addElement($companyother);

1

@fireeyedboy提供的解决方案很方便,但对于这个确切的问题无效。

Zend_Validate_Abstract使用上下文,无法作为变量传递给isValid()。这样,当使用isValid()方法(无论是原始的还是重写的)时,空字段不会被传递和验证(除非您设置了setRequired(true)setAllowEmpty(false),但我们不想要)。因此,在您将两个字段(companynamecompanyother)都留空的情况下,不会发生任何操作。我所知道的唯一解决方案是扩展Zend_Validate类以允许验证空字段。

如果您知道更好的解决方案,请告诉我,因为我也在处理类似的问题。


0

我还没有遇到过这样的解决方案,但它是完全有效的,所以+1。

我会扩展Your_Form::isValid(),包括对这两个元素值的手动检查。

如果所有字段都通过了各自的验证器,那么这种验证可能属于整个表单,因此可以将其放置在表单的验证上而不是字段上。您同意这种思路吗?


0

我同意@chelmertz的观点,这样的功能不存在。

我不同意的是扩展Your_Form::isValid()。相反,我会编写一个自定义验证器,接受必须具有值的两个表单元素的值。这样我就可以在任意表单元素上重复使用它。这与Identical Validator有些相似。


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