Я пытаюсь создать форму адреса с адресом оплаты и доставки. Когда флажок на адресе доставки установлен, я хочу пропустить проверку формы на этом адресе.
Я создал тип формы ниже с опцией переключения, которая будет отображаться и иметь дело с флажком, однако форма все еще проверяется, даже если отмечен.
Symfony имеет документация о том, как реализовать такую форму, и хотя у меня почти такой же код, проверка не отключается при проверке. Я не использую группы проверки, поэтому я просто отключаю группу по умолчанию, чтобы отключить проверку сущности.
AddressType
построение формы для Address
класс (который имеет ограничения аннотации на некоторые поля, такие как NotBlank
а также Callback
).
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options["toggle"]) {
$builder->add("toggle", CheckboxType::class, [
"mapped" => false,
"required" => false,
"label" => $options["toggle"]
]);
}
$builder
->add("name", TextType::class, [
"required" => !$options["toggle"]
])
->add("address", TextType::class, [
"required" => !$options["toggle"]
])
->add("zipcode", TextType::class, [
"label" => "Postcode",
"required" => !$options["toggle"]
])
->add("city", TextType::class, [
"required" => !$options["toggle"]
])
->add("countryCode", ChoiceType::class, [
"choices" => Address::COUNTRY_CODES
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
"toggle" => false,
"data_class" => Address::class,
"validation_groups" => function(FormInterface $form) {
if ($form->has("toggle") && $form->get("toggle")->getData() === true) {
return [];
}
return ["Default"];
}
]);
$resolver->setAllowedTypes("toggle", ["bool", "string"]);
}
}
Я использую тип как это:
$addressForm = $this
->createFormBuilder([
"paymentAddress" => $paymentAddress,
"shippingAddress" => $shippingAddress
])
->add("paymentAddress", AddressType::class, [
"label" => false
])
->add("shippingAddress", AddressType::class, [
"label" => false,
"toggle" => "Use payment address"])
->add("submit", SubmitType::class, [
])
->getForm();
Я изучал это в течение нескольких часов, но я не могу понять, почему проверка не отключена, и я не желаю создавать форму из-за этой маленькой детали.
Почему проверка для AddressType
не отключается закрытием в configureOptions? Если это не так, как это работает, что было бы лучшим решением для частичного отключения проверки аккуратно?
РЕДАКТИРОВАТЬ: даже если настройки "validation_groups" => false
в значениях по умолчанию, в дочерних элементах, созданных в компоновщике, или при использовании формы проверка будет по-прежнему выполняться. Это не связано с закрытием. Каждый онлайн-ресурс, включая собственный ресурс Symfony, утверждает, что он должен работать, хотя …
[…] поэтому я просто отключаю группу по умолчанию, чтобы отключить проверку сущности.
При условии, что Address
свойства & ограничения выглядят так:
/**
* @Assert\NotBlank()
*/
private $name;
// etc.
«Валидатор» предполагает, что эти свойства будут оцениваться с Default
группа, потому что он всегда считает пустым validation_groups
(например. return [];
) как ['Default']
(следовательно, проверка не отключается при проверке):
https://symfony.com/doc/current/validation/groups.html:
Если группы не указаны, все ограничения, принадлежащие группеDefault
будет применяться.
Решение для частичного отключения проверки правильности
Должно быть много способов достичь этого, но я покажу вам два из них:
Если нет data_class
устанавливается в корневую форму, то Form
группа доступна только для проверки этого уровня:
$addressForm = $this
->createFormBuilder([...], [
'validation_groups' => 'Form', // <--- set
])
Далее в configureOptions
метод, набор Address
группа по умолчанию и Form
группа, если «переключатель» отмечен, также добавляет Valid()
ограничение для каскадной проверки:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
// ...
"validation_groups" => function(FormInterface $form) {
if ($form->has("toggle") && $form->get("toggle")->getData() === true) {
return ['Form']; // <--- set
}
return ['Address']; // <--- set
},
'constraints' => [new Assert\Valid()], // <--- set
]);
}
Это означает, что при отправке с выключенным: Form
а также Address
группы применяются к адресным полям, иначе только Form
группа применяется.
(Другой способ) В Address
класс добавляет группу «Required» ко всем ограничениям, это позволяет избежать проверки этих свойств с помощью Default
группа:
/**
* @Assert\NotBlank(groups={"Required"}) // <--- set
*/
private $name;
// etc.
Далее в configureOptions
набор методов Required
в качестве группы по умолчанию и Default
если переключатель отмечен:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
// ...
"validation_groups" => function(FormInterface $form) {
if ($form->has("toggle") && $form->get("toggle")->getData() === true) {
return ['Default']; // <--- set
}
return ['Required']; // <--- set
},
'constraints' => [new Assert\Valid()], // <--- set
]);
}
В этом случае при отправке с выключенным: Default
а также Required
группы применяются к адресным полям, иначе только Default
группа, пропуская при этом обязательные поля.
Вложенные формы, содержащие объекты, отключенные от корневого объекта, можно проверить, установив для параметра ограничений значение new Valid()
,
Других решений пока нет …