1

I have two fields, value and copy that I'm trying to do some custom validation on to make sure they roughly match each other.

So far in my module I have this:

function HOOK_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle)
{
    if(!empty($fields['field_value']) && !empty($fields['field_copy']))
    {
        $fields['field_copy']->addConstraint('CopyMatchesValue');
        $fields['field_value']->addConstraint('CopyMatchesValue');
    }
}

A constraint

<?php

namespace Drupal\MODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Checks that value matches copy
 *
 * @Constraint(
 *   id = "CopyMatchesValue",
 *   label = @Translation("Copy Matches Value", context = "Validation"),
 * )
 */
class CopyMatchesValue extends Constraint
{
    // The message that will be shown if the format is incorrect.
    public $copyValueMismatch = 'The value does not look like it matches the copy.';
}

And a validator

<?php

namespace Drupal\MODULE\Plugin\Validation\Constraint;

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

/**
 * Validates the CopyMatchesValue constraint.
 */
class CopyMatchesValueValidator extends ConstraintValidator
{
  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint)
  {

      foreach ($items as $key => $item) {
          var_dump($item->value);
      }
      exit;

      // do some processing to make sure they match

      $this->context->addViolation();
    }
  }
}

I was expecting $items to have both fields I added the constraint to, but that doesn't seem to be the case.

How can I pass two fields to one validator so that I can validate them against each other?

1

I'm not sure if constraints is the best way to go when you need access to two fields. In your form alter, could you add a custom validation method? That way you would have access to array &$form, FormStateInterface $form_state giving you access to all fields.

$form['#validate'][] = 'my_test_validate';

And then your validation function...

/**
 * {@inheritdoc}
 */
function my_test_validate(array &$form, FormStateInterface $form_state) {
  // Do what you need to do here...
}
  • I was originally going to do is this way, but then everything I could find said that you should't do it that way and to use constraints instead. If I go this route, how can I then set the errors on the fields with the equivalent of $this->context->addViolation? – Samsquanch Aug 3 '17 at 15:40
  • Interesting. I haven't heard that this is no longer the route to go. If you have any backup material for that, I would be curious to give it a look. That said, you can set the error like this... $form_state->setErrorByName('website', $this->t('Invalid URL.')); – xpersonas Aug 3 '17 at 15:43
  • I framed my code around this example which mentions it, but I found that same sentiment in a few other places as well. – Samsquanch Aug 3 '17 at 15:45
  • Ah I see. For an entity, yes that does make sense. I was answering from a custom form approach which is not quite what you intended. – xpersonas Aug 3 '17 at 15:47
  • I'm using this validator on a node_create form, I'm not sure if that matters or not. Is there different validation for entity vs form? – Samsquanch Aug 3 '17 at 15:50
0

In your case, in validate() you should get an entity before. So your code should be like this:

<?php

namespace Drupal\MODULE\Plugin\Validation\Constraint;

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

/**
 * Validates the CopyMatchesValue constraint.
 */
class CopyMatchesValueValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($entity, Constraint $constraint) {
    $entity = $entity->getEntity();
    $field_first = $entity->get('field_first')->getString();
    $field_second = $entity->get('field_second')->getString();
    if ($some_logic) {
      $this->context->addViolation($constraint->message);
    }
  }
}

This one example how I made a similar custom validator for checking the field depending on the value of another field.

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.