提交表单后,子表单值在接收端显示为 null
Posted
技术标签:
【中文标题】提交表单后,子表单值在接收端显示为 null【英文标题】:Subform values are showing up as null on the receiving end after form submit 【发布时间】:2019-02-11 03:13:21 【问题描述】:我已经构建了一个可以正常提交的表单,但是当我在控制器中查看子表单值时,它们在接收端都以 null 结束。
这是我的UserProfileType
表单,基于User
class。具体来说,我们正在查看的子表单是subscriptionTier1
、subscriptionTier1
和subscriptionTier1
:
class UserProfileType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('firstName', TextType::class)
->add('lastName', TextType::class)
->add('email', EmailType::class)
// etc... I'll keep out the unimportant fields
// here are the subforms whose values show up as null on the back end
->add('subscriptionTier1', UserSubscriptionTierType::class, [
'required' => false,
'mapped' => false
])
->add('subscriptionTier2', UserSubscriptionTierType::class, [
'required' => false,
'mapped' => false
])
->add('subscriptionTier3', UserSubscriptionTierType::class, [
'required' => false,
'mapped' => false
])
->add('save', SubmitType::class, [
'attr' => ['class' => 'save'],
])
;
public function configureOptions(OptionsResolver $resolver)
$resolver->setDefaults(array(
'data_class' => User::class,
'mode' => null
)
);
这是我的UserSubscriptionTierType
表单类型类的样子:
class UserSubscriptionTierType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('name', TextType::class, [
'attr' => [
'maxlength' => 25
]
])
->add('price', ChoiceType::class, [
'choices' => [
'$10 per month' => 10,
'$20 per month' => 20,
'$30 per month' => 30
]
])
->add('description', TextareaType::class)
->add('messaging', CheckboxType::class, [
'required' => false
])
;
public function configureOptions(OptionsResolver $resolver)
$resolver->setDefaults(array(
'data_class' => UserSubscriptionTier::class,
));
如下图所示,subform subscriptionTier1的名称、价格、描述值都是在前端设置的:
这是subscriptionTier1
子表单的树枝代码的样子:
<div class="row justify-content-center w-100 ml-0 mr-0 mt-3 tier tier-1" >
<div class="col-lg-6 mt-1">
<div class="form-group form-control-lg w-100">
<label for="firstname" class="mb-2">Tier 1 Name</label>
form_widget(form.subscriptionTier1.name, 'attr': 'class': 'form-control')
</div>
</div>
<div class="col-lg-6 mt-1">
<div class="form-group form-control-lg w-100">
<label for="tier1price" class="mb-2">Tier 1 Price</label>
form_widget(form.subscriptionTier1.price, 'attr': 'class': 'form-control')
</div>
</div>
<div class="col-lg-12 mt-3">
<div class="form-group form-control-lg w-100">
<label for="bio" class="mb-2">Tier 1 Description
<sup class="text-danger">*</sup>
</label>
form_widget(form.subscriptionTier1.description, 'attr': 'class': 'form-control border-box', 'rows':'8')
</div>
</div>
<div class="col-lg-12">
<div class="form-group form-control-lg w-100">
<div class="form-check">
<label class="form-check-label">
form_widget(form.subscriptionTier1.messaging, 'attr': 'class': 'form-control form-check-input')
<span class="form-check-sign"></span>
Enable Messaging
</label>
</div>
</div>
</div>
</div>
这里是接收端的代码,控制器:
public function saveProfileAction(Request $request)
$user = $this->getUser();
$form = $this->createForm(UserProfileType::class, $user);
$form->handleRequest($request);
dump($form->get('subscriptionTier1')->getData());
所以在调试中,如果我只转储第一个表单subscriptionTier1
,你可以看到值都是null
。
ProfileController.php on line 269:
Form #2235 ▼
-config: FormBuilder #2236 ▶
-parent: Form #2112 ▶
-children: OrderedHashMap #2237 ▶
-errors: []
-submitted: true
-clickedButton: null
-modelData: UserSubscriptionTier #2280 ▼
-id: null
-posts: ArrayCollection #2323 ▶
-subscriptions: null
-name: null // Don't understand why this is null
-price: null // Don't understand why this is null
-description: null // Don't understand why this is null
-tierNumber: null
-versionNumber: null
-messaging: false
-user: null
+"subsciptions": ArrayCollection #2089 ▶
-normData: UserSubscriptionTier #2280 ▶
-viewData: UserSubscriptionTier #2280 ▶
-extraData: []
-transformationFailure: null
-defaultDataSet: true
-lockSetData: false
有人知道为什么这些值没有传递到后端(或被清空)吗?
【问题讨论】:
如果它不在Request
对象中(您也可以检查原始$_POST
数据确定),那么您应该检查呈现的html。如果数据没有随请求一起提供,那么您在后端就无能为力了。
【参考方案1】:
由于UserProfileType
表单类型的data_class
选项设置为User
类,模型数据将是User
类的实例,并且由于User
类没有像@987654327 这样的字段@ 等,这些不会出现在您的模型数据中。
相反,您可以像这样在控制器中的表单中访问未映射的字段:
$subscriptionTier1 = $form->get('subscriptionTier1')->getData();
文档here
编辑:您只能在处理完表单并且提交表单后才能访问subscriptionTier1等的值,否则将为null:
public function saveProfileAction(Request $request)
$user = $this->getUser();
$form = $this->createForm(UserProfileType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
$subscriptionTier1 = $form->get('subscriptionTier1')->getData();
dump($subscriptionTier1);
【讨论】:
嗨 iirxs,谢谢,这是一个很大的帮助。现在表单值全部为空。我将不得不编辑问题。但这仍然是一个很大的帮助。 我已经编辑了我的答案以帮助您更好地理解它【参考方案2】:我不知道这是否只是一种解决方法,或者这实际上是最佳实践方式,但这是我如何让它工作的:
我有以下子表单标签:
form_start(form.subscriptionTier1)
etc...
form_end(form.subscriptionTier1)
这将嵌套表单标签。显然,您不允许嵌套这样的表单。
因此,为所有 subscriptionTier1
、subscriptionTier1
、subscriptionTier1
取出 form_start(form.subscriptionTier1)
、 form_end(form.subscriptionTier1)
,然后检查请求对象中的表单值。
【讨论】:
以上是关于提交表单后,子表单值在接收端显示为 null的主要内容,如果未能解决你的问题,请参考以下文章
为什么Django引发IntegrityError:列“user_id”中的null值在提交表单时违反了非空约束?
在使用openfeign做表单提交时,HttpServletRequest传参后服务端接收不到数据的问题