regexzend-framework2zend-formzend-validatezend-inputfilter

How to customise the Regex validation messages in a Zend\Form keeping them reusable?


The default validation error message for Regex is

"The input does not match against pattern '%pattern%'"

I can replace it by a custom one like

"Please make an input according to the pattern '%pattern%'"

But then I still have a not really user-friendly message with the internal regex in it. I also can write

"Only capital letters are allowed"

But in this case I need to write a new message for every single regex field.

Is it possible / How to create own, but still flexible/reusable/parameterizable messages?


An example of what I want:

public function getInputFilterSpecification()
{
    return [
        'foo' => [
            'validators' => [
                [
                    'name' => 'Regex',
                    'options' => [
                        'pattern' => '/^[A-Z0-9:]*$/',
                        'pattern_user_friendly' => 'capital letters, numbers, and colons',
                        'message' => 'The input may only contain the following characters: %pattern_user_friendly%.'
                    ]
                ],
            ]
        ],
        'bar' => [
            'validators' => [
                [
                    'name' => 'Regex',
                    'options' => [
                        // new pattern
                        'pattern' => '/^[A-Z~:\\\\]*$/',
                        // new user friendly pattern description
                        'pattern_user_friendly' => 'capital letters, tildes, colons, and backslashes',
                        // still the same message
                        'message' => 'The input may only contain the following characters: %pattern_user_friendly%.'
                    ]
                ],
            ]
        ],
    ];
}

Solution

  • The solution is to create a custom Validator (extending the Regex), to extend there the list of messageVariables, and to add the logic for setting the value as a property:

    class Regex extends ZendRegex
    {
        protected $patternUserFriendly;
    
        public function __construct($pattern)
        {
            // s. https://github.com/zendframework/zend-validator/blob/master/src/Regex.php#L34-L36
            $this->messageVariables['patternUserFriendly'] = 'patternUserFriendly';
            $this->messageTemplates[self::NOT_MATCH] =
                'The input may only contain the following characters: %patternUserFriendly%.'
            ;
            parent::__construct($pattern);
            if (array_key_exists('patternUserFriendly', $pattern)) {
                $this->patternUserFriendly = $pattern['patternUserFriendly'];
            }
        }
    }
    
    class MyFieldset extends ZendFieldset implements InputFilterProviderInterface
    {
        ...
        public function init()
        {
            parent::init();
            $this->add(
                [
                    'type' => 'text',
                    'name' => 'foo',
                    'options' => [
                        'label' => _('foo')
                    ]
                ]);
            $this->add(
                [
                    'type' => 'text',
                    'name' => 'bar',
                    'options' => [
                        'label' => _('bar')
                    ]
                ]);
        }
        public function getInputFilterSpecification()
        {
            return [
                'bar' => [
                    'validators' => [
                        [
                            'name' => 'MyNamespace\Validator\Regex',
                            'options' => [
                                'pattern' => '/^[a-zA-z]*$/',
                                'patternUserFriendly' => '"a-z", "A-Z"'
                            ]
                        ]
                    ]
                ]
            ];
        }
    }