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:
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”.
Symfony. Cómo detectar cambios en una colección de una entidad
Hoy os traigo una de esas recetas que, si bien está perfectamente documentada en la web de Doctrine, dar con ella no es…
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
From this class I would like to highlight 3 things:
- We need to add the
@Annotationif we want to use this
Constraintthrough annotations in the class to be validated.
$messageproperty can have what you want and will be the error message that the form will contain in case the new
titledoes not pass the validation.
- And finally and most importantly, we need to declare this
CLASS_CONSTRAINTsince we will subsequently need to receive in the validator associated with this
Constraintthe object of the
MyEntityclass and not the
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, the
Validatorclass 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
Constraintthat 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
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
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: