6

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

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

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

注意:验证在过滤值上操作 Zend_Form_Element::isValid() 在验证之前通过提供的过滤器链过滤值。有关详细信息,请参阅过滤器部分。

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

4

4 回答 4

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 以按键添加/删除过滤器等。

怎么想?

于 2011-01-28T13:57:51.267 回答
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
}

我从来没有这样做过,但我想这(或类似的东西)可能会奏效。

于 2011-01-28T00:38:01.953 回答
1

好点子 !,

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

在验证之前对输入执行一些规范化通常是有用的和/或必要的。例如,您可能希望删除所有 HTML,但对剩余的内容运行验证以确保提交有效。或者您可能想要修剪输入周围的空白空间,以便 StringLength 验证器将使用输入的正确长度,而不计算前导或尾随空白字符。

但是当且仅当您无法解决mingos的答案时,必须是帮助

于 2011-01-28T00:42:59.787 回答
1

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

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

于 2011-01-28T03:16:20.637 回答