6

I have an entity that has a field attached to it and the values that user types into the field has to be globally(website) unique(compared to other entities).

I have added validation to the entity form but what if I create this entity programmatically? How can I prevent the entity to be saved into the storage?

I've noticed there is a validate method in ContentEntityBase, though not in ConfigEntityBase. Is this the place for it? If so, I could use some examples.

3 Answers 3

5

Fields have constraints defined on them and as everything is a field on an entity, that's that. See Comment::baseFieldDefinitions does ->setConstraints(array('CommentName' => array()));. Then there's appropriate plugin in the Drupal\comment\Plugin\Validation\Constraint namespace in a class called CommentNameConstraint. The logic is in CommentNameConstraintValidator.

So the chain is

  1. setConstraints in basedFieldDefinitions setting a list of plugin ids (CommentName) and their arguments (empty array in the example
  2. A plugin in the Drupal\modulename\Plugin\Validation\Constraint namespace with the appropriate plugin id. The classname is not magic, the plugin id is what's important. Using the plugin id plus Constraint as classname seems to be best practice.
  3. Whatever classname you picked in the previous step, append Validator to it, make it extend Symfony\Component\Validator\ConstraintValidator and put your validation logic in validate.
6
  • What if the field is Field API field?
    – user21641
    Mar 20, 2014 at 14:40
  • Is it your field type? Then you can control it on the annotation of your class, see EmailItem for an example or by implementing the getConstraints() method if it is dynamic (like based on a setting), see StringItem for an example. When it's a config field from someone else, then I'm not sure.. maybe on the entity itself if controlled there, or you could alter it into the plugin definition if it applies to all fields of that type.
    – Berdir
    Mar 20, 2014 at 15:40
  • No, it's not my field in this case. And even if it were, placing the constraint in it globally is not a good practice.
    – user21641
    Mar 21, 2014 at 11:30
  • It's perfectly good practice if the validation is required for that field type, like an email field must store a valid e-mail address. If you neither control the entity nor the field and it is a configurable field added through the UI then it's currently not possible to add a constraint I think. Feel free to open an issue to add a hook or something for that.
    – Berdir
    Mar 21, 2014 at 16:45
  • Ok, but why it's not possible to add constraint to entity? That would solve my situation perfectly.
    – user21641
    Mar 21, 2014 at 19:41
0

Constraints for fields can be provided at two places: - on a per field-type level, i.e. in its annotation or getConstraints() method - on a per field basis by adding it to the field definitions. Right now, this is only possible for non-configurable fields - e.g. by implementing https://api.drupal.org/api/drupal/core!modules!system!entity.api.php/function/hook_entity_base_field_info_alter/8. It's not possible to add custom constraints to configurable fields right now (sounds like this could need improvement).

1
  • But why then, when we have now "services" that allow communicating with Drupal core via different paths than classic web UI, we don't have such validation in place? I mean what if I want to create some content entity via REST for, lets say a mobile application build on Drupal, and I provide some invalid data. How would by application knew that something is wrong? I don't think validation on form level is sufficient at all.
    – user21641
    Apr 12, 2014 at 18:04
0

I think this has come in more recently change record.

I found this article that really helped when I was writing validation contraints: Introducing Drupal 8's Entity Validation API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.