gremo
gremo

Reputation: 48919

Custom Symfony 2 class constraint validator NotEqualTo

I need to create a Symfony 2 custom class constraint validator, to validate that a property is not equal to another (i.e. password can't match username).

My first question is: do I need to implement method getDefaultOption() and what's is used for?

/**
 * @Annotation
 */
class NotEqualTo extends Constraint
{
    /**
     * @var string
     */
    public $message = "{{ property1 }} should not be equal to {{ property2 }}.";

    /**
     * @var string
     */
    public $property1;

    /**
     * @var string
     */
    public $property2;

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions() { return ['property1', 'property2']; }

    /**
     * {@inheritDoc}
     */
    public function getTargets() { return self::CLASS_CONSTRAINT; }
}

Second question is, how do I get the actual object (to check for "property1" and "property2") in my validate() method?

public function validate($value, Constraint $constraint)
{
    if(null === $value || '' === $value) {
        return;
    }

    if (!is_string($constraint->property1)) {
        throw new UnexpectedTypeException($constraint->property1, 'string');
    }

    if (!is_string($constraint->property2)) {
        throw new UnexpectedTypeException($constraint->property2, 'string');
    }

    // Get the actual value of property1 and property2 in the object

    // Check for equality
    if($object->property1 === $object->property2) {
        $this->context->addViolation($constraint->message, [
            '{{ property1 }}' => $constraint->property1,
            '{{ property2 }}' => $constraint->property2,
        ]);
    }
}

Upvotes: 1

Views: 2019

Answers (1)

Crozin
Crozin

Reputation: 44386

do I need to implement method getDefaultOption() and what's is used for?

You don't have to do that, however it's strongly recommended to do so if your annotation has a single "leading" property. Annotation's properties are defined as a list of key-value pairs, eg:

@MyAnnotation(paramA = "valA", paramB = "valB", paramC = 123)
@MaxValue(value = 199.99)

Using getDefaultOption() you can tell the annotations processor which option is a default one. If you'd define paramA as a default option of @MyAnnotation and value as a default option of @MaxValue you'd be able to write:

@MyAnnotation("valA", paramB = "valB", paramC = 123)
@MaxValue(199.99)
@MaxValue(199.99, message = "The value has to be lower than 199.99")

how do I get the actual object (to check for "property1" and "property2") in my validate() method?

You have to create a class-level constraint annotation. Then $value argument in your validate() method will be a whole object rather a single property.

Upvotes: 3

Related Questions