Match Validator not working - Possible core bug?

So I’m using the match validator with regex pattern and it is not working… like at all. Even using a basic regex such as /[a-z]/, pretty much anything is accepted. Both client-side and server side.

Here are my validation rules:

return [
            ['username', 'trim'],
            ['username', 'required'],
            ['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
            ['username', 'string', 'min' => 4, 'max' => 20],
            ['username', 'match', 'pattern' => '/[a-zA-Z]/', 'message' => 'Only letters can be used' ]

And the view:

<div class="row">
        <div class="col-lg-5">
            <?php $form = ActiveForm::begin([
                'id' => 'form-username',
                'enableClientValidation' => true,
                'validateOnType' => true]); ?>

                <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?> 

                <div class="form-group">
                    <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'submit-button']) ?>

            <?php ActiveForm::end(); ?>

Even with this simple regex, I am able to input any character and it will pass validation on the server side. Either I am doing something wrong, or this is a major bug!

Further, the regex pattern in the validation rules… I’m assuming it’s using php based regex? How is this translated into client side? The documentation does not go into these details.

/[a-zA-Z]/ means that if you have at least one character that is from that range it’s valid. Probably you need /^[a-zA-Z]$/ that will allow only one character from that range. Or /^[a-zA-Z]+$/ that will allow many characters but only from that range.

Thanks for that, but I’m still getting incorrect behavior.

Your /^[a-zA-Z]$/ suggestion works for a single character. However, I tried /\w/ just as a test and inputted a string of special characters such as “$%^#$%^#” and it still passed validation on both sides (client and server).

I know I’m bad at regex, but this seems like something isn’t right here.

And for the record, it fails on these two playgrounds

Also, just did some further testing.

I tried /[a-z]/ as the pattern and entered “a” and the validator said it was invalid.

However, when I tried preg_match('/[a-z]/', 'a') directly, it returns ‘a’ as expected.

Something is definitely up with the validator.

Please paste here your action code.

Isn’t it because ‘a’ is shorter than the minimum length of 4? The string validator with min/max length will be evaluated before the match validator.

For example, '$%^#$a-%#' will match the pattern of '/\w/', because it has an ‘a’ in it. You should have used '/^\w+$/' instead. As @Bizley said, usually you need to use ^ , + and $ in the pattern.

1 Like

My apologies. I wrote my last post in haste and have done a bit more exploring. It seems to be that the issue is that regex in php does not directly translate to regex in javascript on the client side.

This is regex pattern 1:

In PHP, the \z forces the final character to be of the word class. This is what I want…

However, on the client-side… EVERYTHING fails validation.

If I try pattern 2:

This works on both sides, but allows for strings such as “asf_asdf#$^#$%$#”

I did discover that what I want is actually:

Which works server side and client-side.

However, I only discovered through trial and error that the \z doesn’t work on client-side.

I think there needs to be a blurb on the match validator indicating that the exact same regex will be used on client-side and server side with no translation.

I focused on the server side for security.

Not a bug… but definitely worth mentioning I think. Or at least say the \A and \z won’t translate in client-side validation.

Oh, I didn’t know that.
(And in fact I didn’t know \A and \z and have never used them :sweat_smile: … regex is a kind of wild beast.)

1 Like