如何在Zend Framewor 2中为所需的表单字段设置自定义错误消息?

时间:2016-11-05 11:26:12

标签: zend-framework2 zend-form zend-validate validationmessage

在我的Form我有Fieldset,其中包含两个元素foobar。他们的业务规则是,必须设置一个。因此,当设置foobar时,字段集有效,而当没有设置时,字段集无效。

我解决了这个问题如下:

public function getInputFilterSpecification()
{
    return [
        'foo' => [
            'required' => empty($this->get('bar')->getValue())
        ],
        'bar' => [
            'required' => empty($this->get('foo')->getValue())
        ],
    ];
}

工作。但是错误消息仍然存在问题:如果bot字段为空,则用户为每个字段获取消息“值是必需的且不能为空”。用户认为,他必须填写这两个字段。

如何自定义required字段的错误消息,以便显示正确的消息,例如“foo的值是必需的,如果未设置条形,则不能为空“。并且“条形值是必需的,如果没有设置foo,则不能为空。”

2 个答案:

答案 0 :(得分:0)

您可以通过扩展默认链

来创建自定义ValidatorChain

然后您可以覆盖此方法:

/**
 * Returns true if and only if $value passes all validations in the chain
 *
 * Validators are run in the order in which they were added to the chain  (FIFO).
 *
 * @param  mixed $value
 * @param  mixed $context Extra "context" to provide the validator
 * @return bool
 */
 public function isValid($value, $context = null)
 { .. }

默认情况下,如果所有验证器返回true,则此方法仅返回true,但它也可以访问上下文 - 这意味着您也可以获取所有其他字段值。

修改逻辑然后检查其中一个验证器是否为true都很简单。

然后,您只需附加您想要的所有字段"其中一个是必需的"

答案 1 :(得分:-1)

你最终会得到一个像这样的自定义验证器:

ViewDidLoad()

那么如何使用它:

class MyCustomValidator extends ZendAbstractValidator
{
    const FIELDS_EMPTY = 'fieldsEmpty';

    /**
     * Error messages
     *
     * @var array
     */
    protected $abstractMessageTemplates = [
        self::FIELDS_EMPTY => "Vale for %field1% is required and can't be empty, if %field2% is not set.",
    ];

    /**
     * Variables which can be used in the message templates
     *
     * @var array
     */
    protected $abstractMessageVariables = [
        'field1' => 'field1',
        'field2' => 'field2',
    ];

    /**
     * Value of the field
     * @var mixed
     */
    protected $value;

    /**
     * Name of the first field to check, which the validator is bind to
     * @var mixed
     */
    protected $field1;

    /**
     * Name of the second field to check
     * @var string
     */
    protected $field2;

    /**
     * MyCustomValidator constructor.
     *
     * @param array|null|\Traversable $options
     *
     * @throws \Exception
     */
    public function __construct($options)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (!array_key_exists('field1', $options) || !array_key_exists('field2', $options)) {
            throw new \Exception('Options should include both fields to be defined within the form context');
        }

        $this->field1 = $options['field1'];
        $this->field2 = $options['field2'];

        parent::__construct($options);
    }

    /**
     * Returns true if and only if $value meets the validation requirements
     * If $value fails validation, then this method returns false, and
     * getMessages() will return an array of messages that explain why the
     * validation failed.
     *
     * @param  mixed $value
     * @param array  $context
     *
     * @return bool
     */
    public function isValid($value, $context = [])
    {
        $this->setValue($value);

        if (empty($value) && (array_key_exists($this->field2, $context) || empty($context[$this->field2]))) {
            $this->error(self::FIELDS_EMPTY);

            return false;
        }

        return true;
    }
}

对于那些不知道如何注册MyCustomValidator的人 - 在module.config.php中或使用Module.php中的public function getInputFilterSpecification() { return [ 'foo' => [ 'validators' => [ [ 'name' => MyCustomValidator::class, 'options' => [ 'field1' => 'foo', 'field2' => 'bar', ] ] ] ], 'bar' => [ 'validators' => [ [ 'name' => MyCustomValidator::class, 'options' => [ 'field1' => 'bar', 'field2' => 'foo', ] ] ] ], ]; } 。不要同时使用它们,不管是其中之一:

如何在module.config.php中注册

public function getValidatorConfig()

如何在你的module.php中注册:

'validators' => array(
    'factories' => array(
        MyCustomValidator::class => MyCustomValidatorFactory::class,
    ),
 ),

工厂类:

/**
 * Expected to return \Zend\ServiceManager\Config object or array to
 * seed such an object.
 * @return array|\Zend\ServiceManager\Config
 */
public function getValidatorConfig()
{
    return [
        'aliases' => [
            'myCustomValidator' => MyCustomValidator::class,
            'MyCustomValidator' => MyCustomValidator::class,
            'mycustomvalidator' => MyCustomValidator::class,
        ],
        'factories' => [
            MyCustomValidator::class => MyCustomValidatorFactory::class,
        ],
    ];
}

请注意,我保持验证器class MyCustomValidatorFactory implements FactoryInterface, MutableCreationOptionsInterface { /** * Options for the InputFilter * * @var array */ protected $options; /** * Create InputFilter * * @param ServiceLocatorInterface $serviceLocator * * @return BlockChangeOnSerialsValidator */ public function createService(ServiceLocatorInterface $serviceLocator) { return new MyCustomValidator($this->options); } /** * Set creation options * * @param array $options * * @return void */ public function setCreationOptions(array $options) { $this->setOptions($options); } /** * Set options * * @param array $options */ public function setOptions(array $options) { $this->options = $options; } } 方法非常简单,因为我不确定它是否覆盖了您的情况,但这是为了帮助您朝着正确的方向前进。但是可以做的改进是重用NotEmpty验证器来检查字段是否为空。

请注意,当您致电isValid()时,isValid($value, $context = null)表单中的上下文是formData。