Create custom validation constraints in Drupal 10

27 / Feb / 2024 by Dharmendra Singh 0 comments

Introduction

Drupal core uses the validation API(Constraints) to validate the fields, Now, Drupal provides the flexibility to use the core validator to validate your own entity without writing the validation. We can also create a custom validator if needed. For uses constraints to write custom validators.

Limitations on the form based validation

Generally, we use form based validation if we would like to add any validation on the form or entity with the help of HOOK_form_alter, But now, with the help of constraints, we can use the existing validator.

There are some limitations if we use form based validation.

  •  Can not add validation on the entity fields without adding the form validation
  •  Create a node from REST API, it does not trigger the validation because the form does not render,

We can add validation to the fields/entities with the help of constraints, which are implemented as plugins.

Creating a custom constraint requires three steps

  • Define the constraint
  • Create the validation for the constraint
  • Set the constraint to the entity type or field it needs to validate

Step : 1: Define the Constraints

The constraint definition will go in the namespace Drupal\[MODULENAME]\Plugin\Validation\Constraint and will extend Symfony\Component\Validator\Constraint. In this class, the types of constraint violations are defined, along with the error messages that will be displayed for the given violations.

Filename: IntegerConstraint.php

<?php
namespace Drupal\learning\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;

/**
 * Checks that the submitted value is a unique integer.
 *
 * @Constraint(
 *   id = "Integer",
 *   label = @Translation("Integer", context = "Validation"),
 *   type = "string"
 * )
 */

class IntegerConstraint extends Constraint {
  // The message that will be shown if the value is not an integer.
  public $notIntegerMessage = '%value is not an integer';
}

Step 2: Create the Validator for the Constraint

The next step is to create the class that will validate the constraint.

The constraint validation will go in the namespace Drupal\[MODULENAME]\Plugin\Validation\Constraint and will extend Symfony\Component\Validator\ConstraintValidator. In this class, the submitted values will be returned, and any violations will be registered.

Filename : IntegerConstraintValidator.php

<?php

namespace Drupal\learning\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
 * Validates the Integer constraint.
 */
class IntegerConstraintValidator extends ConstraintValidator {
  /**
   * {@inheritdoc}
   */
  public function validate($value, Constraint $constraint) {
    foreach ($value as $item) {
      if (!is_int($item->value)) {
        $this->context->addViolation($constraint->notIntegerMessage, ['%value' => $item->value]);
      }
    }
  }
}

Step 3: Set the Constraint to the Entity or Field it Needs to Validate

Drupal provides some hooks to trigger the validation constraints.

3.1 – Adding a Constraint to the Bundle Field of an Entity/content Type

This method is used to add constraints to a field on an entity type defined in an other module or field added in the entity manually. but not the core field like entity title, created etc.

/**
 * Implements hook_entity_bundle_field_info_alter().
 */
function learning_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
  //Here test is the content type, and i added a field {field_name}
  if ($entity_type->id() === 'node' && $bundle === 'test') {
    if (isset($fields['field_name'])) {
      // Use the ID as defined in the annotation of the constraint definition
      $fields['field_name']->addConstraint('Integer');
    }
  }
}

3.2 Adding a Constraint to an Entity Type Not Defined by Your Module

This hook is used to add constraints to whole entity type hook_entity_type_alter()

/**
 * Implements hook_entity_type_alter().
 */
  function learning_entity_type_alter(array &$entity_types) {
    // Add validation constraint to the node entity
    $entity_types['node']->addConstraint('Integer');
  }

3.3 Adding a Constraint to an Entity basefield

/**
 * Implements hook_entity_base_field_info_alter().
 */
function learning_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
    if ($entity_type->id() == 'node' && !empty($fields['title'])) {
      $fields['title']->addConstraint('Integer');
    }
  }
validation constraint

Conclusion 

We learned about the validator and its uses and also explored how to create custom constraints within Drupal 10.

We can create any kind of validator and reuse that code anywhere in the application. Some of the core constraint validators already exist in the Drupal core, to check the existing constraints follow the reference link.

Reference :

Drupal custom constraints – https://api.drupal.org/api/drupal/9/search/ConstraintValidator

FOUND THIS USEFUL? SHARE IT

Tag -

Drupal

Leave a Reply

Your email address will not be published. Required fields are marked *