How to add a custom validation for the custom entity?

Hello! In this article I would like to describe how we can add custom validation

for our custom entity type.

Let’s use a ´our_custom_module_name´ module, as example, to create an entity validation,
which will check if we have the same entity already (with the same title).

Inside the module folder we should create a constraint:

Constraints in Drupal 8 are also plugins which usually hold a small amount of information about how data is actually being validated, what error message should be used in case of failure and any additional options the validator needs.

/our_custom_module_name/src/Plugin/Validation/Constraint/ExistsEntityWithNameConstraint.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
/**
* @file
* Contains \Drupal\our_custom_module_name\Plugin\Validation\Constraint\ExistsEntityWithNameConstraint.
*/
namespace Drupal\our_custom_module_name\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Constraint for checking if a default entity already exists.
*
* @Constraint(
* id = "ExistsEntityWithName",
* label = @Translation("Entity exists", context = "Validation"),
* type = { "entity" }
* )
*/
class ExistsEntityWithNameConstraint extends Constraint {
/**
* Message shown when the entity already exists.
*
* @var string
*/
public $messageExists = 'Entity %entity already exists';
}

Next, we should create a validator class, where all our validation logic should be placed:

The validator class (which is referenced by the constraint) is responsible for checking the data.

/our_custom_module_name/src/Plugin/Validation/Constraint/ExistsEntityWithNameConstraintValidator.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
/**
* @file
* Contains \Drupal\our_custom_module_name\Plugin\Validation\Constraint\ExistsEntityWithNameConstraintValidator.
*/
namespace Drupal\our_custom_module_name\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the ExistsEntityWithNameConstraint.
*/
class ExistsEntityWithNameConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* Validator 2.5 and upwards compatible execution context.
*
* @var \Symfony\Component\Validator\Context\ExecutionContextInterface
*/
protected $context;
/**
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* Constructs a new ExistsEntityWithNameConstraintValidator.
*
* @param \Drupal\Core\Entity\EntityTypeManager
* The user storage handler.
*/
public function __construct(EntityTypeManager $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('entity_type.manager'));
}
/**
* {@inheritdoc}
*
* Here we validate entities and check if the same entity
* (with the same name) already exists.
*/
public function validate($entity, Constraint $constraint) {
$name = $entity->name->value;
if (isset($name)) {
$entity_storage = $this->entityTypeManager->getStorage($entity->bundle());
// Check if we already have the same entity.
$ex_entity = $entity_storage->loadByProperties(array('name'=> $name));
if (!empty($ex_entity) && is_array($ex_entity)) {
// Takes entity id.
$ex_entity_id = array_shift($ex_entity)->id();
// If we just update the same entity, then skip validation.
if ($entity->id() != $ex_entity_id) {
$this->context->buildViolation($constraint->messageExists, array(
'%entity' => $name
))
->atPath('name')
->addViolation();
}
}
}
}
}

And last step. We should add annotation to our custom entity to use this validation:

1
2
3
4
5
...
constraints = {
"ExistsEntityWithName" = {}
}
...
Share Comments