Vil*_*men 6 php forms validation symfony
我正在尝试创建一个带有付款和送货地址的地址表单。检查送货地址上的复选框时,我想跳过该地址上发生的表单验证。
我在下面创建了带有切换选项的表单类型,该选项将显示和处理复选框,但是即使选中该表单,该表单仍会得到验证。
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"]);
}
}
Run Code Online (Sandbox Code Playgroud)
我使用这样的类型:
$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();
Run Code Online (Sandbox Code Playgroud)
我已经讨论了几个小时,但我无法推断为什么验证没有被关闭,而且我不愿意在这个小细节上搞砸一个表格。
为什么AddressTypeconfigureOptions 中的闭包未关闭验证?如果这不是它的工作原理,那么以整洁的方式完成部分关闭验证的更好解决方案是什么?
编辑:即使"validation_groups" => false在默认值、在构建器中创建的子项中或在表单的使用中进行设置,验证仍然会发生。它与关闭无关。每个在线资源,包括 Symfony 自己的资源,都声明它应该可以工作……
[...]所以我只是禁用默认组来禁用实体上的验证。
假设Address属性和约束如下所示:
/**
* @Assert\NotBlank()
*/
private $name;
// etc.
Run Code Online (Sandbox Code Playgroud)
“验证器”假设这些属性将使用Default组进行评估,因为它始终将空validation_groups(例如 return [];)视为['Default'](因此在检查时不会关闭验证):
https://symfony.com/doc/current/validation/groups.html
Default:如果未指定组,则将应用属于该组的所有约束。
一种以简洁的方式完成部分关闭验证的解决方案
应该有很多方法可以实现它,但我向您展示其中两种:
如果data_class根表单没有设置,则Form组仅可用于验证此级别:
$addressForm = $this
->createFormBuilder([...], [
'validation_groups' => 'Form', // <--- set
])
Run Code Online (Sandbox Code Playgroud)
接下来,在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
]);
}
Run Code Online (Sandbox Code Playgroud)
这意味着,在提交时关闭切换:Form并将Address组应用于地址字段,否则仅Form应用组。
(另一种方式)在Address类中将“必需”组添加到所有约束中,它避免使用Default组验证这些属性:
/**
* @Assert\NotBlank(groups={"Required"}) // <--- set
*/
private $name;
// etc.
Run Code Online (Sandbox Code Playgroud)
接下来,在设置为默认组的configureOptions方法中,如果选中切换:RequiredDefault
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
]);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,提交时切换关闭:Default并且Required组应用于地址字段,否则仅Default分组,从而跳过必填字段。
可以通过将约束选项设置为 来验证包含与根对象断开连接的对象的嵌套表单new Valid()。
| 归档时间: |
|
| 查看次数: |
2569 次 |
| 最近记录: |