Backend Development - Validation Constraints

In earlier topics, we explored the Typed Data API and saw how Drupal defines structured data for fields and entities. Now we move into one of the most important layers of backend integrity: Validation Constraints.

Validation constraints define the rules that data must follow before it is saved.

They ensure that:

  • Invalid data does not enter the system
  • Business rules are enforced consistently
  • APIs respect validation rules
  • Forms and programmatic saves behave the same way

Constraints integrate directly with the Typed Data system, which means validation is centralized and reusable.

This topic continues the learning-by-building approach using the same weeklydrupal_demo module and our custom rating field.

By the end of this article, you will understand:

  • What validation constraints are
  • How constraints integrate with Typed Data
  • How to add constraints to fields
  • How to create custom constraint plugins
  • Best practices for backend validation design

1. What Is a Validation Constraint

A constraint is a rule that validates data.

Examples in core:

  • Required
  • Length
  • Range
  • Email
  • Unique

Constraints are evaluated before an entity is saved.

If validation fails, the save operation is blocked.


2. Where Validation Happens

Validation occurs:

  • During form submission
  • During programmatic entity save
  • During REST API requests
  • During batch and queue processing (if entities are validated)

Validation is not limited to forms. It is part of the entity system.


3. Adding Constraints to a Field Type

We previously defined the rating field type. Now we improve it.

In RatingItem.php:

use Drupal\Core\TypedData\DataDefinition;

public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
  $properties['value'] = DataDefinition::create('integer')
    ->setLabel(t('Rating value'))
    ->setRequired(TRUE)
    ->addConstraint('Range', ['min' => 1, 'max' => 5]);

  return $properties;
}

What is happening

  • setRequired(TRUE) ensures value cannot be empty
  • Range constraint ensures rating is between 1 and 5
  • Validation is now automatic everywhere

No additional form validation code is required.


4. How Entity Validation Works

Before saving:

$violations = $entity->validate();

if (count($violations) > 0) {
  foreach ($violations as $violation) {
    \Drupal::logger('weeklydrupal_demo')->error($violation->getMessage());
  }
}

If there are violations, Drupal prevents saving.

This applies to:

  • Form submissions
  • Programmatic saves
  • REST imports

5. Creating a Custom Constraint Plugin

When built-in constraints are not enough, create a custom one.

Example: rating must not be 3 (just for demonstration).

File structure

src/Plugin/Validation/Constraint/NoThreeConstraint.php
src/Plugin/Validation/Constraint/NoThreeConstraintValidator.php

NoThreeConstraint.php

namespace Drupal\weeklydrupal_demo\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * @Constraint(
 *   id = "NoThree",
 *   label = @Translation("No Three Allowed"),
 *   type = "integer"
 * )
 */
class NoThreeConstraint extends Constraint {
  public $message = 'Rating value of 3 is not allowed.';
}

NoThreeConstraintValidator.php

namespace Drupal\weeklydrupal_demo\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class NoThreeConstraintValidator extends ConstraintValidator {

  public function validate($value, Constraint $constraint) {
    if ($value == 3) {
      $this->context->addViolation($constraint->message);
    }
  }
}

6. Attaching Custom Constraint to Field

Modify property definition:

->addConstraint('NoThree');

Now validation will reject value 3.


7. How Constraints Integrate with Typed Data

Constraints are attached to:

  • Typed data definitions
  • Field item properties
  • Entity properties

Typed Data defines structure.
Constraints define rules.

Together they ensure safe backend architecture.


8. Best Practices for Validation

  • Use built-in constraints whenever possible
  • Avoid duplicating validation logic in forms
  • Keep constraints focused and reusable
  • Avoid heavy processing inside validators
  • Log violations for debugging

Validation should be centralized, not scattered.


9. Common Mistakes to Avoid

  • Writing custom form validation when constraint is better
  • Skipping validation during programmatic saves
  • Performing business logic inside constraint validators
  • Ignoring multilingual validation considerations

Constraints should enforce data rules, not workflow logic.


10. Learning by Building: weeklydrupal_demo

Extend the demo module by:

  • Adding Range constraint to rating
  • Adding custom NoThree constraint
  • Testing via form and programmatic save
  • Logging violations

This connects:

  • Typed Data API
  • Entity API
  • Field system
  • Form validation

11. Why Validation Constraints Matter

Understanding validation constraints allows you to:

  • Protect data integrity
  • Enforce business rules
  • Build safer APIs
  • Avoid inconsistent validation logic

Validation is a core backend architecture responsibility.