Проверка формы Symfony2 на основе двух полей
В настоящее время я разрабатываю веб-сайт, на котором пользователь может купить подарочные карты. Я использую трехэтапную форму, используя пакет CraueFormFlow, и все это касается шагов. Я могу проверить каждый простой Assert (например, не пустой, адрес электронной почты, повторяющиеся поля и т.д.), Но я столкнулся с ситуацией, когда пользователь может выбрать 0 подарочных карт и перейти на следующую страницу.
Пользователи могут выбрать количество подарочных карт, которые они хотят купить, используя два отдельных: один для подарочных карт на 25 долларов и один для подарочных карт на 50 $. Поэтому я не могу просто поставить валидатор, говорящий, что "значение 0 не разрешено". Валидатор должен запретить пользователю оставлять количество "0" в обоих количествах (25 $и 50 $).
Кто-нибудь знает, как сделать пользовательскую проверку для поиска значений в двух полях?
Спасибо заранее!
Ответы
Ответ 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;