New in Symfony 4.3: Automatic validation

Contributed by
Kévin Dunglas
in #27735.

Consider the following simple Doctrine entity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use Doctrine\ORM\Mapping as ORM;

/** @ORM\Entity */
class SomeEntity
{
    // ...

    /** @ORM\Column(length=4) */
    public $pinCode;
}

Will the following code result in a validation error?

1
2
3
$entity = new SomeEntity();
$entity->pinCode = '1234567890';
$violationList = $validator->validate($entity);

The answer is ... no. Surprisingly, many Symfony developers still don't realize that the Doctrine mapping configuration (e.g. @ORM\Column(length=4)) doesn't actually validate anything. This config is just a hint for the Doctrine schema generator. This can lead to usability and even security issues.

In Symfony 4.3 we improved this by introducing automatic validation based on Doctrine mapping. That's why in Symfony 4.3, the previous example would have produced the following result:

1
2
3
4
5
6
$violationList = $validator->validate($entity);

var_dump((string) $violationList);
// Object(App\Entity\SomeEntity).columnLength:\n
//     This value is too long. It should have 4 characters or less.
//     (code d94b19cc-114f-4f44-9cc4-4138e80a87b9)\n

This new feature introspects mappings like @ORM\Column(length=4) to add the related @Assert\Length(max=4) validation automatically to that same property. Specifically, the following validations are automated:

Doctrine mapping Automatic validation constraint
nullable=false @Assert\NotNull
type=... @Assert\Type(...)
unique=true @UniqueEntity
length=... @Assert\Length(...)

The automatic validation of nullable=false and type=... requires to have the PropertyInfo component installed. Also, this new feature will be disabled by default, but enabled for new projects.

Since the Form component as well as API Platform internally use the Validator component, all your forms and web APIs will also automatically benefit from these automatic constraints.

Lastly, keep in mind that, although this automatic validation is convenient, it's not enough for most applications, so you will still need to manually configure more Symfony validation constraints.

Comments

Nice job !
Awesome
Seems to be a nice new feature :)

As it will be opt-in (so disabled by default for existing Sf apps) could you add the required configuration for existing apps? Thanks :)
I guess the validation constraint for the doctrine mapping of nullable=false should be Assert\NotNull rather than for doctrine mapping of nullable=true ?
@Oliver yes! that was a mistake and it's now fixed.

@Jonathan the code to make this configurable in DoctrineBundle is still pending. I'll update the post when it's merged. Thanks.
Very clever, nice job
Symfony 4.3 is going to be really awesome! 🎉
Love it!
Very nice addition, thanks!
length doesn‘t actually validate anything?

Oh boy, I have to overthink my whole application
It would be nice to mention in the post how exactly to enable/disable this feature
@Tito the option to enable/disable this feature is not ready yet. See https://github.com/doctrine/DoctrineBundle/pull/939 We'll update the blog post when this is ready.
awesome....
Awesome feature! Nice job, thanks
Nice job ! The minimum validation requirements are now free ! Thanks.
Nice and useful update ! Can't wait to put hands on Symfony 4.3 :D
Looks nice for the common case.

But ... how does this handle custom field types that extend basic field types? Not that I would do this, but assuming I would extend an int type to store the year of something and the phpvalue would be a DateTime. Or I have some Object (in php) that is mapped to some string with known max length (in db)? I could have a length attribute in the definition, but the value might be an object. Are lifecycle handlers run before/after validation? Can this "magic" validation be enabled/disabled globally only? What if the db field is not nullable (-> NotBlank?) but the mapper of the custom type will ensure that it is not null? or the lifecycle handler does ensure this?

I see so many edge cases with this ... and have the feeling it would be better to explicitly state that doctrine annotations are not validation constraints (which seems somewhat obvious...).
Login with SymfonyConnect to post a comment