Drupal 8 Create custom validation constraint

How to create custom validation constraint ?

In the previous post i wrote about How to add constraint to filed in a content type, in this one i'm gonna write about how to create your own custom constraints:

First of all what constraint mean?

According to Symfony documentation page Validation Constraints Reference :

The Validator is designed to validate objects against constraints. In real life, a constraint could be: "The cake must not be burned". In Symfony, constraints are similar: They are assertions that a condition is true.

Because of Drupal 8 based on Symfony 4 so you have all those constraints comes with Symofny listed here Validation Constraints Reference, and other ones i listed here How to add constraint to filed in a content type comes with Drupal Core.

So first check if the constraint you need doesn't exist already!

Let's assume that you need to make field that accept only french phone numbers, so you will need a custom validation constraint.

To create custom constraint

  1. You should create a constraint plugin to do so create your plugin class inside YOURMODULE/src/Plugin/Validation/Constraint 
    it should named like [CONSTRAINT_NAME]Constraint and extends Symfony\Component\Validator\Constraint:
    <?php
    
    namespace Drupal\YOUR_MODULE\Plugin\Validation\Constraint;
    
    use Symfony\Component\Validator\Constraint;
    
    /**
     * Checks that the phone is in french format.
     *
     * @Constraint(
     *   id = "FrenchPhone",
     *   label = @Translation("FrenchPhone", context = "Validation"),
     * )
     */
    class FrenchPhoneConstraint extends Constraint {
    
      // The message that will be shown if the format is incorrect.
      public $incorrectPhoneFormat = 'The phone format is incorrect. You provided %phone';
    }
    
  2. Create your constraint validation class should be [CONSTRAINT_NAME]ConstraintValidator should extends the Symfony\Component\Validator\ConstraintValidator class.
    <?php
    
    namespace Drupal\YOUR_MODULE\Plugin\Validation\Constraint;
    
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    
    /**
     * Validates the phone constraint.
     */
    class FrenchPhoneConstraintValidator extends ConstraintValidator {
    
      /**
       * Checks if the passed value is valid.
       *
       * @param mixed $value The value that should be validated
       * @param Constraint $constraint The constraint for the validation
       *
       * @return null
       */
      public function validate($value, Constraint $constraint) {
        // If there is no value we don't need to validate anything
        if (!isset($value) || $value == '') {
          return NULL;
        }
        // Checks if the passed value is valid.
        if (!preg_match('/^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/', $value)) {
          $this->context->addViolation($constraint->incorrectPhoneFormat, ['%phone' => $value]);
        }
      }
    
    }
    

 

Now just clear the cache and follow one of the two ways described here to add your new constraint to your fields!