【问题标题】:How to make this Filter run after this Validator如何让这个过滤器在这个验证器之后运行
【发布时间】:2011-01-28 00:25:51
【问题描述】:

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    当然,创建一个支持验证后过滤的自定义元素似乎是可行的方法。这个怎么样:

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

    你怎么想的?

    【讨论】:

    • +1。看起来很不错。我也不知道 setPostValidateFilters() 方法会被自动调用(是吗?)键'postValidateFilters'。
    • @Marcin:我认为这就是选项的工作方式。如果存在与选项名称“匹配”的方法,则在 setOptions() 期间调用该方法。
    【解决方案2】:

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

    $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
    }
    

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

    【讨论】:

    • +1 这是一个可能的解决方案,但不确定我是否喜欢它。如果所有其他方法都失败了,我会这样做,但我更愿意保持控制器精简,并将过滤逻辑与它所属的表单元素保持一致。
    • 当然,我也希望将其保留在表单代码中,但我想不出任何其他方式来影响调用验证器和过滤器的顺序。我有时也会向控制器添加一些内容,理想情况下应该驻留在表单中,例如,当且仅当检查/填充其他内容时才需要一组字段。您无法在客户端或在用户填写表单之前可靠地检查这一点,因此有时需要在控制器中执行一些额外的表单魔术,无论喜欢与否:(。
    【解决方案3】:

    好点! ,

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

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

    但当且仅当你万一不能解决mingos的答案时,必须是帮助

    【讨论】:

    • 我认为这是一个设计缺陷。一些过滤器非常复杂,它们会进行修改,这可能会使输入无效。所以过滤器应该分为2种。您提到的规范化过滤器,例如需要在验证之前运行的修剪,以及进行更复杂修改的其他过滤器。然后开发者可以在添加过滤器时选择何时触发此过滤器。
    【解决方案4】:

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

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

    【讨论】:

    • 这是一个有趣的想法。我看到的唯一问题是我自动放弃了所有其他过滤器。如果我对未过滤的值进行修改,那么我会丢失修剪过滤器。出于这个原因,到目前为止,明戈的回答可能给了我想要的效果,尽管我不喜欢它在控制器中。如果开发人员可以指定他想要的验证器和过滤器的确切顺序,那将是理想的。
    • @jblue。因此,您希望在验证后只应用一个过滤器,其余的以正常方式应用,是吗?当然,这仍然可以通过制作您的自定义文本元素来完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 2011-04-23
    • 2015-07-21
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多