SymfonyWorld Online 2021 Winter Edition December 9 – 10, 2021 100% Online +20 talks and workshops

New in Symfony 5.4: Nested Validation Attributes

Symfony 5.4 is backed by Private Packagist. Private Packagist is a fast, reliable, and secure Composer repository for your private packages. It mirrors all your open-source dependencies for better availability and monitors them for security vulnerabilities.

Contributed by
Alexandre Daubois
in #41994.

In Symfony 5.2 we added a feature to define validation constraints as PHP attributes. Attributes were very recent at that time, because they had just been added to PHP 8.0. The only caveat was that you couldn't nest PHP attributes, so you couldn't use them with constraints such as AtLeastOneOf and Collection.

Thankfully, PHP 8.1, released on November 25, 2021, adds support for nested attributes. That's why in Symfony 5.4 you'll be able to use PHP attributes to define all existing constraints, without any exemption.

The trick that enables this feature is to use the new keyword to create the nested attribute:

1
2
3
4
5
6
7
#[Attribute1(new SubAttribute1())]
#[Attribute2([new SubAttribute2(), new SubAttribute3()])]
#[Attribute3(someProperty: new SubAttribute4())]
class SomeClass
{
    // ...
}

This is how it looks in practice when using Symfony Validator constraints in a complex example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use Symfony\Component\Validator\Constraints as Assert;

class SomeClass
{
    #[Assert\All([
        new Assert\NotNull(),
        new Assert\Range(min: 3),
    ])]
    #[Assert\Collection(
        fields: [
            'foo' => [
                new Assert\NotNull(),
                new Assert\Range(min: 3),
            ],
            'bar' => new Assert\Range(min: 5),
            'baz' => new Assert\Required([new Assert\Email()]),
            'qux' => new Assert\Optional([new Assert\NotBlank()]),
        ],
        allowExtraFields: true
    )]
    private $property1;

    #[Assert\AtLeastOneOf(
        constraints: [
            new Assert\NotNull(),
            new Assert\Range(min: 3),
        ],
        message: 'foo',
        includeInternalMessages: false,
    )]
    #[Assert\Sequentially([
        new Assert\NotBlank(),
        new Assert\Range(min: 5),
    ])]
    private $property2;

    // ...
}
Help the Symfony project!

As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.

Comments

👏🏻
Login with SymfonyConnect to post a comment