Search code examples
formssymfonyconstraints

Symfony forms Length constraint overrides NotBlank constraint


So in my form I have a field to insert password. On the field in the formbuilder I added 2 constraints; one for if the field is empty and one for if the password is too short.

new NotBlank([
    'message' => 'reset.password.error.enterpassword',
]),
new Length([
    'min' => 6,
    'minMessage' => 'reset.password.error.passwordtooshort',
    // max length allowed by Symfony for security reasons
    'max' => 4096,
]),

However, when I leave the password field empty, it will use the Length constraint (I kind of understand, as the password with length 0 is lower than 6), but shouldn't it use the NotBlank constraint since it's defined?

I also tried putting it after the Length constraint but it still didn't work.


Solution

  • Since Symfony version 5.x, you can use Sequentially to run your assertions in your preferred order.

    new Sequentially([
        new NotBlank([
            'message' => 'reset.password.error.enterpassword',
        ]),
        new Length([
            'allowEmptyString' => true,
            'min' => 6,
            'minMessage' => 'reset.password.error.passwordtooshort',
            // max length allowed by Symfony for security reasons
            'max' => 4096,
        ])
    ]);
    

    The below solution is valid up until Symfony 5.x, when allowemptystring was deprecated:

    The behaviour of the Length validator has changed in recent symfony versions.

    Formerly it did not match empty inputs.

    The option allowEmptyString controls wether empty strings are allowed.

    It defaults to false while older symfony versions defaulted to true.

    See the documentation Length#allowemptystring.

    Set allowEmptyString to true to solve your issue:

    new Length([
        'allowEmptyString' => true,
        'min' => 6,
        'minMessage' => 'reset.password.error.passwordtooshort',
        // max length allowed by Symfony for security reasons
        'max' => 4096,
    ]),
    new NotBlank([
        'message' => 'reset.password.error.enterpassword',
    ]),