4

In Drupal 8, how do I validate a ConfigEntity? I tried adding constraints, but then I found out this only works for ContentEntity, not ConfigEntity.

My ConfigEntity has 2 fields, and the options of the second field should be limited based on what's selected in the first.

Through Drupals #ajax mechanism I can limit the items in the second dropdown - that all works. However, with Javascript disabled or when creating the ConfigEntity programmatically, someone can still select a wrong value for the second dropdown, that doesn't work with the first dropdown selection. I checked ConfigEntityBase but couldn't find anything related to validation.

4

It depends on how your config-entities are created. If the only way to create them is via a form, then you could just override the validateForm method in your form to ensure the entity is valid. In this context the entity should be available by running this code

$form_state->cleanValues();
$this->entity = $this->buildEntity($form, $form_state);

This is what content entity forms do (see \Drupal\Core\Entity\ContentEntityForm::validateForm).

However if you expect your entities to be added programatically or via REST and you need lower-level validation, then you could add a validate method to you entity and call this from the preSave method. Having it available as a public method (validate) would allow other consumers of your API to check if the entity was valid before they called save, thus avoiding the exception.

In terms of the contents of the validate method, you have lots of options. You could try and piggy-back onto core's constraint system - which uses plugins to define constraints. Or you could keep it simple and just return an array of errors. Finally you could keep use a middle-ground and just integrate with the validator component in the Symfony way, which would at least keep your validate return consistent with those for Content entities - something like so:

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Validation;

/**
 * Validates my config entity.
 *
 * @return \Symfony\Component\Validator\ConstraintViolationList 
 *   List of violations. Empty if valid.
 */
public function validate() {
  $validator = Validation::createValidator();
    ->addMethodMapping('loadValidatorMetadata')
    ->getValidator();
  return $validator->validate($this);
}

/**
 * Defines validation rules for this config entity.
 */
public static function loadValidatorMetadata(ClassMetadata $metadata) {
  // Same validator rules.
  // Add your own as required.
  // Note this is static, so you don't have $this in scope.
  $metadata->addPropertyConstraint('someProperty', new Assert\NotBlank(['message' => 'Some property cannot be blank']));
  // But if you add a validation callback, you can operate in the context
  // of an instance.
  $metadata->addConstraint(new Assert\Callback(['methods' => ['someValidationCallback']]));
}

/**
 * Validation callback for some field.
 */
public function someValidationCallback(ExecutionContextInterface $context) {
  if ($this->something === 'something it should not be') {
      $context->buildViolation("Can't let you do that Dave.")
      ->atPath('something')
      ->addViolation();
    }
}
  • How about when the entity is a core config entity? How would you add constraints then? – ssibal Aug 5 at 9:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.