Подтвердить что ты не робот

Проверка формы Symfony2 на основе двух полей

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

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

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

Спасибо заранее!

4b9b3361

Ответ 1

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

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

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

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

class MyConstraint extends Constraint
{
    // ...

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

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

Ответ 2

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

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

        )
    );

Ответ 3

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

В этом классе я проверяю значение свойства 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/

Ответ 4

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

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

Ниже приведен пример проверки pincode, здесь в поле pincode я допускаю только цифры 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')));


    }

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

включенный в ваш класс Entity

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

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

Ответ 5

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

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