如何在此Validator之后运行此Filter

时间:2011-01-28 00:25:51

标签: php zend-framework zend-validate zend-filter

我有一个元素。我想为它添加自定义验证器和自定义过滤器。验证器确保输入是几个允许值之一,然后过滤器将一些自定义值添加到输入。这意味着我必须在运行过滤器之前先验证原始输入。我按此顺序执行

$element = new Zend_Form_Element_Text('element');
$element->addValidator('PermittedValue', false);
$element->addFilter('TotalHyphen', false);
$this->addElement($element);

但这个顺序没有受到尊重。过滤器首先运行并更改数据,然后验证器在过滤的数据上运行,这意味着即使对于有效输入它也总是失败。从documentation看来,这是故意的

  

注意:验证在过滤时运行   值Zend_Form_Element :: isValid()   通过提供的过滤值   验证前过滤链。看到   过滤器部分了解更多信息   信息。

如何指定验证器和过滤器的运行顺序?

4 个答案:

答案 0 :(得分:7)

当然,似乎要创建一个支持后验证过滤的自定义元素。怎么样:

/**
 * An element that supports post-validation filtering
 */
class My_Form_Element_PostValidateFilterable extends Zend_Form_Element_Text
{
    protected $_postValidateFilters = array();

    public function setPostValidateFilters(array $filters)
    {
        $this->_postValidateFilters = $filters;
        return $this;
    }

    public function getPostValidateFilters()
    {
        return $this->_postValidateFilters;
    }

    public function isValid($value, $context = null)
    {
        $isValid = parent::isValid($value, $context);
        if ($isValid){
            foreach ($this->getPostValidateFilters() as $filter){
                $value = $filter->filter($value);
            }
            $this->setValue($value);
        }
        return $isValid;
    }
}

用法是这样的:

$elt = $form->addElement('PostValidateFilterable', 'myElement', array(
     'label' => 'MyLabel',
     'filters' => array(
         'StringTrim',
         // etc
     ),
     'validators' => array(
         'NotEmpty',
         // etc 
     ),
     // here comes the good stuff
     'postValidateFilters' => array(
         new My_Filter_RunAfterValidateOne(),
         new My_Filter_RunAfterValidateTwo(),
     ),
));

这样可以保持表单中的验证和过滤 - 保持控制器很薄。

未经测试,只是在黑暗中刺伤。当然,您可以通过密钥等方式增加/修改API来增加/删除过滤器

Whaddya认为?

答案 1 :(得分:4)

也许根本不添加过滤器。首先在控制器中验证内容,然后单独使用过滤器:

$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getParams())) {
    $filter = new Filter_Whatever();
    $val = $filter->filter($request->getParam('element'));
    ... //call your model or whatever
}

我从来没有这样做过,但我认为这(或类似的东西)可能有用。

答案 2 :(得分:1)

好点! ,

在验证输入之前,应该或必须运行AFAIK过滤器: 来自ZF docs

  

这通常是有用的和/或必要的   对输入执行一些规范化   在验证之前。例如,你   可能想要删除所有HTML,但是   对剩下的内容进行验证   确保提交有效。要么   你可能想修剪空的空间   周围输入使a   StringLength验证器将使用   正确的输入长度没有   计算领先或尾随   空白字符。

但当且仅当你遇到无法解决mingos答案的情况时,必须是帮助

答案 3 :(得分:1)

您希望实现的是更改文本元素处理方式的默认行为。因此,我认为您可以创建自己的元素(例如My_Form_Element_Text),该元素扩展Zend_Form_Element_Text并重载其isValid()方法。

具体来说,您可以在原始的isValid()方法中更改第二行,从$value = $this->getValue();更改为$value = $this->getUnfilteredValue();。这样,您的验证将使用未过滤的值执行。