Symfony 7.3 introduces several enhancements to the Validator component, focusing on developer experience, better configurability, and more expressive constraint definitions.

Allow to Disable Translation

Alexandre Daubois
Contributed by Alexandre Daubois in #50797

The Validator component already allows disabling translation of error messages. However, doing this inside a full-stack Symfony application has been cumbersome. Symfony 7.3 adds a new framework.validation.disable_translation boolean option to make this easier to configure when needed.

Applying Other Constraints in When Constraint

Alexandre Daubois
Contributed by Alexandre Daubois in #59634

The When constraint allows applying validation constraints only when a given expression returns true. In Symfony 7.3, it gains a new otherwise option to define constraints to apply when the expression returns false.

For example, a Coupon discount that can be defined either as a relative percentage or an absolute amount can be validated like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Coupon
{
    #[Assert\GreaterThan(0)]
    #[Assert\When(
        expression: 'this.getType() == "percent"',
        constraints: [
            new Assert\LessThanOrEqual(100, message: 'The percent discount should be between 1 and 100')
        ],
        otherwise: [
            new Assert\LessThan(9999, message: 'The monetary discount should be less than 9999')
        ],
    )]
    private ?int $discount;

    // ...
}

Deprecated Option Arrays

Christian Flothmann
Contributed by Christian Flothmann in #54744

Until now, validation constraints could be configured using either named arguments or associative arrays. For example:

1
2
3
4
5
6
7
8
9
new Assert\Choice(
    choices: ['fiction', 'non-fiction'],
    message: 'Choose a valid genre.',
);

new Assert\Choice([
    'choices' => ['fiction', 'non-fiction'],
    'message' => 'Choose a valid genre.',
]);

Supporting both syntaxes makes the internal implementation more complex. Symfony 7.3 deprecates the associative array syntax, and it is now recommended to always use named arguments.

New Options for File Constraint

Issam Raouf
Contributed by Issam Raouf in #58485

The File constraint checks whether a value is a valid file path or File object. One of its options, filenameMaxLength, ensures that file names do not exceed a specific length.

However, counting characters is not as simple as using PHP's strlen(). What if the file name contains multibyte or grapheme-based characters? Symfony 7.3 adds two new options to make this more robust:

  • filenameCountUnit, defines how characters are counted. It supports:

    • FILENAME_COUNT_BYTES (default): uses strlen()
    • FILENAME_COUNT_CODEPOINTS: uses mb_strlen()
    • FILENAME_COUNT_GRAPHEMES: uses grapheme_strlen()
  • filenameCharset, defines the charset used by mb_strlen() (only used when the unit is CODEPOINTS)

Improved Image Constraint for SVG images

Maxime COLIN
Contributed by Maxime COLIN in #59265

The Image constraint validates many aspects of image files, such as maximum dimensions, pixel count, and MIME types. Symfony 7.3 improves support for SVG images: all options related to aspect ratio (allowLandscape, allowPortrait, allowSquare, maxRatio, and minRatio) now apply to SVG files as well.

Multiple Unique Errors

Hubert Lenoir
Contributed by Hubert Lenoir in #59274

The Unique constraint checks if at least one element in a collection is duplicated. Previously, only the first duplicate triggered a validation error:

1
2
3
4
5
$violations = $this->validator->validate(
    ['a1', 'a2', 'a1', 'a1', 'a2'],
    new Unique(),
);
// Output: 1 violation on [2]

Symfony 7.3 introduces a new stopOnFirstError option. When set to false, all duplicates are reported:

1
2
3
4
5
$violations = $this->validator->validate(
    ['a1', 'a2', 'a1', 'a1', 'a2'],
    new Unique(stopOnFirstError: false),
);
// Output: 3 violations on [2], [3] and [4]

Closures Support in When Constraint

Alexandre Daubois
Contributed by Alexandre Daubois in #59800

Starting with PHP 8.5 (planned for November 2025), it's possible to use static callables inside attribute expressions. Symfony 7.3 anticipates this by allowing closures in the When constraint expression:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\When;

class BlogPost
{
    #[When(expression: static function (BlogPost $subject) {
        return $subject->published && !$subject->draft;
    }, constraints: [
        new NotNull(),
        new NotBlank(),
    ])]
    public ?string $content;

    public bool $published;

    public bool $draft;
}
Published in #Living on the edge