【问题标题】:Required option of the filter deactivates validation in ZF3过滤器的必需选项禁用 ZF3 中的验证
【发布时间】:2018-03-11 04:39:44
【问题描述】:

在 ZF3 中,我创建了一个包含两个字段的表单:文本和 url。用户只能填写其中一项,并且必须至少填写一项。

想象一下:可以放网站的内容或网站的网址。该表单可用于从网站或文本中获取某些数据。

我准备了两个验证器类。每个输入一个。这些类从上下文参数中获取另一个类的输入值。 StringLength 验证器用于这两个字段。

这几乎可以正常工作,但是当两个字段都提交为空时,就会出现不好的问题。然后数据确实通过了验证,而它应该没有。

在此问题的情况下,字段 required 变为 false。

当我将它们切换为 true 时,两个字段都需要,但我只需要一个。

所以目标是当两个字段都为空时,验证结果将变为 false。然后应该出现唯一一条消息。我的意思是这样的消息或多或少:One of fields must be filled out. 不是“必需”消息。

这里是表单类和两个验证器类。

<?php

namespace Application\Filter;

use Application\Form\Test as Form;
use Application\Validator\Text;
use Application\Validator\Url;
use Zend\InputFilter\InputFilter;

class Test extends InputFilter
{
    public function init()
    {
        $this->add([
            'name' => Form::TEXT,
            'required' => false,
            'validators' => [
                ['name' => Text::class],
            ],
        ]);
        $this->add([
            'name' => Form::URL,
            'required' => false,
            'validators' => [
                ['name' => Url::class],
            ],
        ]);
    }
}

<?php

namespace Application\Validator;

use Zend\Validator\StringLength;
use Zend\Validator\ValidatorInterface;

class Text implements ValidatorInterface
{
    protected $stringLength;
    protected $messages = [];

    public function __construct()
    {
        $this->stringLengthValidator = new StringLength();
    }

    public function isValid($value, $context = null)
    {
        if (empty($context['url'])) {
            $this->stringLengthValidator->setMin(3);
            $this->stringLengthValidator->setMax(5000);

            if ($this->stringLengthValidator->isValid($value)) {
                return true;
            }
            $this->messages = $this->stringLengthValidator->getMessages();

            return false;
        }
        if (!empty($value)) return false;
    }

    public function getMessages()
    {
        return $this->messages;
    }
}

<?php

namespace Application\Validator;

use Zend\Validator\StringLength;
use Zend\Validator\ValidatorInterface;

class Url implements ValidatorInterface
{
    const ERROR_NOT_ALLOWED_STRING = 'string-not-allowed';
    protected $stringLength;
    protected $messages = [
        self::ERROR_NOT_ALLOWED_STRING => 'Only one of text and url field may by filled.',
    ];

    public function __construct()
    {
        $this->stringLengthValidator = new StringLength();
    }

    public function isValid($value, $context = null)
    {
        if (empty($context['text'])) {
            $this->stringLengthValidator->setMin(3);
            $this->stringLengthValidator->setMax(500);

            if ($this->stringLengthValidator->isValid($value)) {
                return true;
            }
            $this->messages = $this->stringLengthValidator->getMessages();

            return false;
        }
        if (!empty($value)) return false;
    }

    public function getMessages()
    {
        return $this->messages;
    }
}

更新

我使用了来自@Crisp 的建议,并且不得不在代码中进行一些更正。添加了返回和消息处理。工作代码如下:

<?php

namespace Application\Filter;

use Application\Form\Test as Form;
use Application\Validator\Text;
use Application\Validator\Url;
use Zend\InputFilter\InputFilter;

class Test extends InputFilter
{
    public function init()
    {
        $this->add([
            'name' => Form::TEXT,
            'required' => false,
            'allow_empty' => true,
            'continue_if_empty' => true,
            'validators' => [
                ['name' => Text::class],
            ],
        ]);
        $this->add([
            'name' => Form::URL,
            'required' => false,
            'allow_empty' => true,
            'continue_if_empty' => true,
            'validators' => [
                ['name' => Url::class],
            ],
        ]);
    }
}

<?php

namespace Application\Validator;

use Zend\Validator\StringLength;
use Zend\Validator\ValidatorInterface;

class Text implements ValidatorInterface
{
    protected $stringLength;
    protected $messages = [];

    public function __construct()
    {
        $this->stringLengthValidator = new StringLength();
    }

    public function isValid($value, $context = null)
    {
        if (empty($context['url'])) {
            if (empty($value)) return false;
            $this->stringLengthValidator->setMin(3);
            $this->stringLengthValidator->setMax(5000);

            if ($this->stringLengthValidator->isValid($value)) {
                return true;
            }
            $this->messages = $this->stringLengthValidator->getMessages();

            return false;
        }
        if (!empty($value)) return false;
        return true;
    }

    public function getMessages()
    {
        return $this->messages;
    }
}

<?php

namespace Application\Validator;

use Zend\Validator\StringLength;
use Zend\Validator\ValidatorInterface;

class Url implements ValidatorInterface
{
    const ERROR_NOT_ALLOWED_STRING = 'string-not-allowed';
    const ERROR_EMPTY_FIELDS = 'empty-fields';
    protected $stringLength;
    protected $messages = [
        self::ERROR_NOT_ALLOWED_STRING => 'Only one of text and url field may be filled out.',
    ];

    public function __construct()
    {
        $this->stringLengthValidator = new StringLength();
    }

    public function isValid($value, $context = null)
    {
        if (empty($context['text'])) {
            if (empty($value)) {
                $this->messages = [
                    self::ERROR_EMPTY_FIELDS => 'One of the fields must be filled out.',
                ];
                return false;
            }
            $this->stringLengthValidator->setMin(3);
            $this->stringLengthValidator->setMax(500);

            if ($this->stringLengthValidator->isValid($value)) {
                return true;
            }
            $this->messages = $this->stringLengthValidator->getMessages();
            return false;
        }
        if (!empty($value)) return false;
        return true;
    }

    public function getMessages()
    {
        return $this->messages;
    }
}

【问题讨论】:

    标签: php validation filter zend-framework3


    【解决方案1】:

    为确保您的验证器始终运行,即使是空值,您需要在输入规范中添加 allow_emptycontinue_if_empty 选项。否则,任何不是required 的值都会跳过验证。

    以下组合应该可以工作

    class Test extends InputFilter
    {
        public function init()
        {
            $this->add([
                'name' => Form::TEXT,
                'required' => false,
                'allow_empty' => true,
                'continue_if_empty' => true,
                'validators' => [
                    ['name' => Text::class],
                ],
            ]);
            $this->add([
                'name' => Form::URL,
                'required' => false,
                'allow_empty' => true,
                'continue_if_empty' => true,
                'validators' => [
                    ['name' => Url::class],
                ],
            ]);
        }
    }
    

    该组合应确保在遇到空值时应用您的验证器。

    Rob Allen (@akrabat) 写了一篇有用的博文,详细介绍了值得收藏的组合akrabat.com/zend-input-empty-values/

    【讨论】:

      猜你喜欢
      • 2020-05-02
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      • 2021-04-25
      • 2011-07-16
      • 1970-01-01
      相关资源
      最近更新 更多