Symfony. Validate an object based on its previous version
How to validate an object using the Validator component of Symfony and taking into account its previous version
Today I bring you one of those recipes for Symfony that is always good to know if at any time we find the opportunity to apply it. Basically, what I intend in this article is to teach you to validate an object that we are persisting through Doctrine based on the value it had previously.
In other words, suppose we have the entity:

and a MyEntityFormType
class that represents the form with which we create and modify objects of this class:

What we are looking for is to add a validation to the title
field so that, depending on the value it had previously, the new value is valid or not. For example, we are going to work on the following validation: the length of the value entered for title
must always be greater than that of the previous value. That is, if before title
stored the string “Title”, a new valid value would be “Another Title” but not “Title”.
This recipe will also allow us to familiarize ourselves with the Validator component as well as with the Doctrine UnitOfWork concept of which I talked to you before on this article:
So I encourage you to reach the end because I think it is very interesting.
So that said, let’s go there.
Defining a “Constraint class”
Since Symfony and the Validator component allow us to solve the case we have raised with one of the Constraints that we have by default, what we will have to do is create our own.
So the first thing we will do is create a class called TitleLength
inside the src src/Validator/Constraints
folder:

From this class I would like to highlight 3 things:
- We need to add the
Annotation
@Annotation
if we want to use thisConstraint
through annotations in the class to be validated. - The
$message
property can have what you want and will be the error message that the form will contain in case the newtitle
does not pass the validation. - And finally and most importantly, we need to declare this
Constraint
as aCLASS_CONSTRAINT
since we will subsequently need to receive in the validator associated with thisConstraint
the object of theMyEntity
class and not thetitle
property.
Defining a “Validator” class
That said, the next thing we will do is write the validator of this Constraint
. To do this, we will create a class called TitleLengthValidator
within it where we create the constraint.
Symfony is able to automatically associate the validator associated with each
Constraint
. For this, theValidator
class will be named as “constraint name + Validator”

To perform the validation, the first thing we will need is the EntityManager
, so we inject it using the Symfony autowire.
Once this is done, we will write the validate
method which receives two arguments:
- The value or object to validate
- The
Constraint
that is being validated
Since what we want is to check the length of the new title with that of the previous one, we will need to recover that previous value. This is where knowing the concept of Doctrine UnitOfWork
becomes important, because thanks to these “work units” we can retrieve the object as it is in the database.
¡Wow! Please, clarify UnitOfWork concept
Imagine we want to edit objects of the MyEntity
class. What we will have done in our controller will have been to retrieve it by id
through the associated repository, create a form of the MyEntityFormType
class by passing said object and associate that form to the Request
through the handleRequest
method:

Thus, when the user submits the form, the handleRequest
method will map the values sent to the $obj
object so it will now contain the values sent and not those found in the database.
That is why we need to use a Doctrine UnitOfWork
to retrieve the previous values (those found in the database), since if we tried using $myEntityRepo->findOneById(1)
what Doctrine would do would be to return a “cached” version “with the new values, it will consider that this reference has it already loaded in memory and it is not necessary to go to search for it in the database.
Let’s continue with the TitleLengthValidator class
Now I think it is clearer why we need to declare the constraint as CLASS_CONSTRAINT
, because what we need is to receive the object in the validator in order to be able to recover it through the UnitOfWork
.
Explained this, the rest of the code of the TitleLengthValidator
class is quite simple: we will verify that the length of the new value exceeds that of the old value and if not, we will create an error.
Associate the TitleLength constraint with the entity
And the last step will be to associate our constraint with the entity. I will use annotations for convenience, for which we will go to src/Entity/MyEntity.php
and add what you see below:

In this way, whenever we are going to create or modify an object of the MyEntity
class, our TitleLength
constraint will be checked.
¿Quieres recibir más artículos como este?
Suscríbete a nuestra newsletter: