自定义验证器Symfony2订购

时间:2013-02-11 23:14:18

标签: forms validation symfony symfony-2.1

我有一个实体,其中包含一些自定义验证器,如下所示:

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;
[...]

我的问题是如何设定检查顺序......

我想首先验证我的属性,如果属性有效,那么我想检查这两个属性是否允许“一起”......

所以我的情况需要验证者的特定顺序。

请问如何实现?

目前的问题是我的班级验证'ConstrainsGiftValid'在他们面前开始; S

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:1)

要检查$username$productName是否在一起,您必须创建custom validation constraint

如果您需要验证程序的特定订单,并希望稍后在代码中重复使用这两个字段的验证,我认为应该这样做:

1 为{username和productName}创建表单类型。

2 在该formType上应用验证规则。如果要使用验证顺序,则需要在此特定情况下对整个表单应用约束。因此,您只能按照自己想要的顺序抛出错误。

3 您最终可以将formType嵌入GiftFormType。不要忘记使用有效约束或将cascade_validation选项设置为true来验证嵌入的表单。

答案 1 :(得分:1)

好的,将一切限制在一个约束中。

这包括对特定属性的绑定错误以及针对不同故障的错误消息:

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;
}