4
votes

I have an Entity with a few custom validators as in:

use Digital\ApplicationBundle\Validator\Constraints\ConstrainsUsername;
use Digital\ApplicationBundle\Validator\Constraints\ConstrainsProduct;
use Digital\ApplicationBundle\Validator\Constraints\ConstrainsGiftValid;

/**
 * @DigitalAssert\ConstrainsGiftValid
 */
class Gift
{

/**
 * @DigitalAssert\ConstrainsUsername
 */
private $username;

/**
 * @DigitalAssert\ConstrainsProduct
 */
private $productName;
[...]

My question is how i can set an order of checking....

I would like to validate my properties first and if properties are valid then I would like to check if those 2 properties are allowed to 'be' together...

So my case requires specific order of the validator.

How this could be accomplished please?

Current issue is my class validation 'ConstrainsGiftValid' kicks in before them ;S

Any help much appreciated.

2

2 Answers

1
votes

To check if $username and $productName go together, you would have to create a custom validation constraint.

If you require a specific order of the validator, and would like to reuse the validation of these 2 fields later in your code, I think this should do it:

1 Create a form type for {username and productName}.

2 Apply your validation rules on that formType. You'll need to apply the constraints on the entire form in this particular case if you want to play with the order of validation. You can therefore only throw the errors if you want to and in the order you want.

3You can finally embed that formType within your GiftFormType. Don't forget to use Valid constraint or set cascade_validation option to true to validate the embedded form.

1
votes

OK, handing everything in one constraint worked.

This includes binding error to specific property and erroring different messages for different failures:

public function isValid($gift, Constraint $constraint)
{

    // Validate product.
    /** @var $product Product */
    $product = $this->em->getRepository('DigitalApplicationBundle:Shop\Product')->findOneBy(array('name' => $gift->getProductName()));
    if (!$product instanceof Product) {

        $this->context->addViolationAtSubPath('username', $constraint->messageProduct, array('%string%' => $gift->getProductName()), null);
        return false;

    }

    // Validate user.
    /** @var $user User */
    $user = $this->em->getRepository('DigitalUserBundle:User')->findOneBy(array('username' => $gift->getUsername()));
    if (!$user instanceof User) {

        $this->context->addViolationAtSubPath('username', $constraint->messageUser, array('%string%' => $gift->getUsername()), null);
        return false;
    }


    // Gift correct type of the item!
    if (($product->getType() != 0) && ($user->getGender() !== $product->getType())) {

        $this->context->addViolationAtSubPath('username', $constraint->messageType, array('%string%' => $gift->getProductName()), null);
        return false;

    }

    // If already owning this product.
    foreach ($user->getWardrobe()->getProducts() as $wardrobeProduct) {
        if ($product == $wardrobeProduct) {

            $this->context->addViolationAtSubPath('username', $constraint->message, array('%string%' => $gift->getProductName(), '%user%' => $gift->getUsername()), null);
            return false;
        }
    }

    return true;
}