Проверка формы Symfony2 на основе двух полей - PullRequest
20 голосов
/ 17 ноября 2011

В настоящее время я разрабатываю веб-сайт, на котором пользователь может покупать подарочные карты. Я использую трехэтапную форму, используя пакет CraueFormFlow, и все относится к шагам. Я могу проверить каждое простое утверждение (например, не пустое, электронная почта, повторные поля и т. Д.), Но я столкнулся с ситуацией, когда пользователь может выбрать 0 подарочных карт и перейти на следующую страницу.

Пользователи могут выбрать количество подарочных карт, которые они хотят купить, используя две отдельные: одну за 25 $ подарочные карты и одну за 50 $ подарочные карты. Поэтому я не могу просто поставить валидатор, говорящий «значение 0 не разрешено». Валидатор должен запретить пользователю оставлять количество «0» в обеих суммах (25 $ и 50 $).

Кто-нибудь знает, как сделать пользовательскую проверку, ища значения в двух полях?

Заранее спасибо!

Ответы [ 5 ]

37 голосов
/ 17 ноября 2011

У вас есть много решений для этого.

Самый простой способ - добавить ограничение обратного вызова к классу вашей модели.

Еще один способ сделать это - создать собственное ограничение и связанный с ним валидатор. У вас есть поваренная книга, объясняющая, как создать пользовательское ограничение проверки . Это лучший способ сделать это.

Поскольку ваше ограничение применяется не к свойству, а к классу, вы должны указать его, переопределяя метод ->getTargets() вашего класса ограничений:

class MyConstraint extends Constraint
{
    // ...

    public function getTargets()
    {
        return Constraint::CLASS_CONSTRAINT;
    }
}

Таким образом, значение, переданное в качестве аргумента $value метода ->isValid(), будет содержать значения всего класса, а не только одного свойства.

12 голосов
/ 06 февраля 2014

Если у вас нет класса данных, присоединенного к вашей форме, вы можете реализовать зависимые ограничения в формах, подобных этой:

    $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,

        )
    );
7 голосов
/ 19 июля 2014

Вот как я сделал это в моих ограничениях проверки, чтобы проверить срок действия кредитной карты со свойствами месяца и года истечения срока действия.

В этом классе я проверяю значение свойства expirationYear и сравниваю его со значениемсвойства expirationMonth, полученного из contextObject.

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

Конечно, вы должны авторизовать ограничения класса и свойств в вашем методе getTargets, сформировать основной файл ограничений.

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

Дополнительные пояснения иполное руководство здесь: http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/

3 голосов
/ 15 сентября 2016

Я бы предложил использовать Ограничение выражения .Это ограничение может быть применено к полю формы или (предпочтительно) в сущности:

   /**
     * @var int
     * @Assert\Type(type="integer")
     */
    private $amountGiftCards25;

    /**
     * @var int
     * @Assert\Type(type="integer")
     * @Assert\Expression(expression="this.getAmountGiftCards25() > 0 or value > 0", message="Please choose amount of gift cards.")
     */
    private $amountGiftCards50;
3 голосов
/ 19 декабря 2011

Использование порядка регулярных выражений для предотвращения нуля

В своем классе Entity запишите приведенную ниже функцию переопределения и укажите свойство, которое необходимо проверить.

Приведенный ниже пример предназначен для проверки пин-кода, здесь, в поле пин-кода, я допускаю только комбинации чисел от 0-9 до 10 цифр.

"^ \ d + $" это регулярное выражение, которое я использовал для предотвращения других символов.

Для переопределения этой функции вы должны включить следующие классы

use Symfony\Component\Validator\Mapping\ClassMetadata;// for overriding function loadValidatorMetadata()

use Symfony\Component\Validator\Constraints\NotBlank;// for notblank constrain

use Symfony\Component\Validator\Constraints\Email;//for email constrain

use Symfony\Component\Validator\Constraints\MinLength;// for minimum length

use Symfony\Component\Validator\Constraints\MaxLength; // for maximum length

use Symfony\Component\Validator\Constraints\Choice; // for choice fields

use Symfony\Component\Validator\Constraints\Regex; // for regular expression



public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('pincode', new NotBlank(array('message' => 'Does not blank')));
        $metadata->addPropertyConstraint('pincode', new Regex(array('pattern'=>'/^\d+$/','message' => 'must be number')));
        $metadata->addPropertyConstraint('pincode', new MaxLength(array('limit'=>'6','message' => 'must maximum 6 digits')));
        $metadata->addPropertyConstraint('pincode', new MinLength(array('limit'=>'6','message' => 'must minimum 6 digits')));


    }

Не забывайте, все это должно

входит в ваш класс сущностей

что вы должны подтвердить. Так что в вашем случае используйте правильное регулярное выражение, которое не допускает '0'.

Счастливое кодирование

...