New in Symfony 4.3: Automatic validation
April 2, 2019 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
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.
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 are closed.
To ensure that comments stay relevant, they are closed for old posts.
As it will be opt-in (so disabled by default for existing Sf apps) could you add the required configuration for existing apps? Thanks :)
@Jonathan the code to make this configurable in DoctrineBundle is still pending. I'll update the post when it's merged. Thanks.
Oh boy, I have to overthink my whole application
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...).
- Multi-step forms: when not all fields are shown in the form. Example: when the fields in the next step won't be visible, and if they are required... will it throw a validation error because the entity has a nullable=false field with no value?
- What about validation groups? Is it going to affect only to Default, or any validation group?
- Also about nullable=false with Assert\NotNull. As Jochen said, I had to switch to use NotBlank. Now it looks like this feature will use Assert\NotNull. Are you going to change NotNull behavior to not allow empty strings, or is Doctrine going to store null in the database when empty strings are received?