Drupal 8 custom validation of multiple entity fields
In a recent Drupal 8.6 project, I was using the media entity type to add custom fields to pdf documents. These pdf files contain two fields: a select list and a text field. When a specific select option is chosen, the text field becomes required. I could have used a form alter function to add my custom validation for these fields, but this would limit my validation to just one form. This wouldn't work for entities that were created with JSON API or other methods.
I began by reading a few articles online that nudged me in the right direction:
- https://www.drupal.org/docs/8/api/entity-validation-api/providing-a-cus…
- https://www.bluestatedigital.com/ideas/drupal8-data-validation/
These were great in helping me to get my constraints setup within my custom module. However, they were a bit limiting because they were written for validating individual fields and didn't have the multiple field dependency that I needed.
My search continued and I came upon this posting, https://drupal.stackexchange.com/a/215280, which led me to the comment module in core. Here, I found the CommentNameConstraint.php and CommentNameConstraintValidator.php files. A working example of dependent fields being validated.
Using this as a model, I wrote my constraint and validator classes within my custom module.
namespace Drupal\mymodule\Plugin\Validation\Constraint;
use Drupal\Core\Entity\Plugin\Validation\Constraint\CompositeConstraintBase;
/**
* Verify that the order number is valid.
*
* @Constraint(
* id = "OrderNumber",
* label = @Translation("Order Number", context = "Validation"),
* type = "entity:media"
* )
*/
class OrderNumberConstraint extends CompositeConstraintBase {
/**
* @var string
*/
public $orderNumberRequired = 'The order number is required when the resolution is entered.';
/**
* @var string
*/
public $orderNumberEmpty = 'The order number should not contain a value.';
/**
* {@inheritdoc}
*/
public function coversFields() {
return ['field_order_number', 'field_resolution'];
}
}