Symfony2表单基于两个字段进行验证

Jea*_*lin 20 forms validation symfony

我目前正在开发一个用户可以购买礼品卡的网站.我使用CraueFormFlow捆绑包使用三步形式,一切都与步骤有关.我能够验证每个简单的断言(如非空白,电子邮件,重复字段等)但我面临的情况是,用户可以选择0礼品卡并继续下一页.

用户可以使用两个单独的选择来选择他们想要购买的礼品卡的数量:一个用于25美元礼品卡,一个用于50美元礼品卡.所以我不能只是把一个验证器说"不允许值0".验证器必须防止用户在数量(25 $和50 $)中留下数量"0".

有谁知道如何进行自定义验证以查找两个字段中的值?

提前致谢!

小智 37

你有很多解决方案.

最简单的方法是向模型类添加Callback约束.

另一种方法是创建自定义约束及其关联的验证器.您有一本解释如何创建自定义验证约束食谱.这是做到这一点的最佳方法.

由于您的约束不适用于属性而是适用于类,因此必须指定它覆盖->getTargets()约束类的方法:

class MyConstraint extends Constraint
{
    // ...

    public function getTargets()
    {
        return Constraint::CLASS_CONSTRAINT;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,作为方法$value参数传递的值->isValid()将包含整个类的值,而不仅仅是单个属性的值.

  • 你能解释一下如何实现回调约束吗?我正在查看Symfony2文档,我不太清楚如何访问我想在[...] isValid()函数中检查的值. (4认同)

小智 12

当您没有附加到表单的数据类时,您可以在这样的表单中实现依赖约束:

    $startRangeCallback = function ($object, ExecutionContextInterface $context) use ($form)
    {
        $data = $form->getData();
        $rangeEnd = $data['range_end'];
        if($object && $rangeEnd){
            if ($object->getTimestamp() > $rangeEnd->getTimestamp()) {
                $context->addViolation('Start date should be before end date!', array(), null);
            }
        }

    };

    $form->add('range_start', 'bootstrap_datepicker', array(
            'format' => 'dd-MM-yyyy',
            'required' => false,
            'attr' => array('class' => "col-xs-2"),
            'calendar_weeks' => true,
            'clear_btn' => true,
            'constraints' => array(
                new Callback(array($startRangeCallback)),
            )
        )
    );

    $form->add('range_end', 'bootstrap_datepicker', array(
            'format' => 'dd-MM-yyyy',
            'required' => false,
            'attr' => array('class' => "col-xs-2"),
            'calendar_weeks' => true,
            'clear_btn' => true,

        )
    );
Run Code Online (Sandbox Code Playgroud)


Edo*_*mbo 7

这就是我在验证约束中完成此操作的方法,用于检查信用卡有效期和月份和年份属性.

在这个类中,我检查expirationYear属性的值,并将其与从contextObject获取的expirationMonth属性的值进行比较.

/**
 * Method to validate
 * 
 * @param string                                  $value      Property value    
 * @param \Symfony\Component\Validator\Constraint $constraint All properties
 * 
 * @return boolean
 */
public function validate($value, Constraint $constraint)
{
    $date               = getdate();
    $year               = (string) $date['year'];
    $month              = (string) $date['mon'];

    $yearLastDigits     = substr($year, 2);
    $monthLastDigits    = $month;
    $otherFieldValue    = $this->context->getRoot()->get('expirationMonth')->getData();

    if (!empty($otherFieldValue) && ($value <= $yearLastDigits) && 
            ($otherFieldValue <= $monthLastDigits)) {
        $this->context->addViolation(
            $constraint->message,
            array('%string%' => $value)
        );            
        return false;            
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

当然,您必须在getTargets方法中授权类和属性约束,形成主约束文件.

/**
 * Get class constraints and properties
 * 
 * @return array
 */
public function getTargets()
{
    return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
} 
Run Code Online (Sandbox Code Playgroud)

这里有进一步的解释和完整的教程:http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/