Php 根据Symfony 3.3中的url参数动态设置表单字段
我用的是symfony3.3。我有一个表单,它需要根据url中的参数动态显示一些字段 用户最初会看到一个只有主题字段的表单。之后,他选择一个主题,表单中的一些字段要么隐藏,要么显示。有些字段可以为空,因此不必填写 我创建了一个Php 根据Symfony 3.3中的url参数动态设置表单字段,php,symfony,symfony-forms,Php,Symfony,Symfony Forms,我用的是symfony3.3。我有一个表单,它需要根据url中的参数动态显示一些字段 用户最初会看到一个只有主题字段的表单。之后,他选择一个主题,表单中的一些字段要么隐藏,要么显示。有些字段可以为空,因此不必填写 我创建了一个表单,如下所示 就我而言,感觉和看起来都是一团糟。我对symfony很陌生,关于这个特定场景的文档要么不存在,要么我似乎找不到 const CONTACT_CHOICE_BLANK = 'blank'; const CONTACT_CHOICE_REGISTER = 're
表单
,如下所示
就我而言,感觉和看起来都是一团糟。我对symfony很陌生,关于这个特定场景的文档要么不存在,要么我似乎找不到
const CONTACT_CHOICE_BLANK = 'blank';
const CONTACT_CHOICE_REGISTER = 'register';
const CONTACT_CHOICE_COMPANY = 'company';
const CONTACT_CHOICE_CONTACT = 'contact';
....
/**
* @return string
*/
private function getChoice() {
if($this->requestStack->getCurrentRequest()->query->has('subject')) {
$subject = $this->requestStack->getCurrentRequest()->query->get('subject');
switch($subject){
case self::CONTACT_CHOICE_REGISTER:
$default_choice = 'contact.form.select.option.' . self::CONTACT_CHOICE_REGISTER;
break;
case self::CONTACT_CHOICE_COMPANY:
$default_choice = 'contact.form.select.option.' . self::CONTACT_CHOICE_COMPANY;
break;
case self::CONTACT_CHOICE_CONTACT:
$default_choice = 'contact.form.select.option.' . self::CONTACT_CHOICE_CONTACT;
break;
case self::CONTACT_CHOICE_BLANK:
default:
$default_choice = 'contact.form.select.option.' . self::CONTACT_CHOICE_BLANK;
break;
}
return $default_choice;
}
return self::CONTACT_CHOICE_BLANK;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$default_choice = $this->getChoice();
$this->session->set('show_message', false);
$this->session->set('show_email', false);
$this->session->set('show_company', false);
$this->session->set('show_email_pro', false);
$this->session->set('show_company_spouse', false);
$builder
->add('subject', ChoiceType::class, array(
'choices' => array(
'contact.form.select.option.' . self::CONTACT_CHOICE_BLANK => self::CONTACT_CHOICE_BLANK,
'contact.form.select.option.' . self::CONTACT_CHOICE_REGISTER => self::CONTACT_CHOICE_REGISTER,
'contact.form.select.option.' . self::CONTACT_CHOICE_COMPANY => self::CONTACT_CHOICE_COMPANY,
'contact.form.select.option.' . self::CONTACT_CHOICE_CONTACT => self::CONTACT_CHOICE_CONTACT,
),
'label' => 'contact.form.select.subject',
'required' => true,
'data' => $default_choice,
))
->add('firstName', TextType::class, array('label' => 'contact.form.input.firstname'))
->add('familyName', TextType::class, array('label' => 'contact.form.input.familyname'))
->add('phoneNumber', TextType::class, array('label' => 'contact.form.input.phone'))
->add('contactReason', ChoiceType::class, array(
'choices' => array(
'contact.form.select.option.advertising' => 'contact.form.select.option.advertising',
'contact.form.select.option.internet' => 'contact.form.select.option.internet',
'contact.form.select.option.member' => 'contact.form.select.option.member',
'contact.form.select.option.word' => 'contact.form.select.option.word',
'contact.form.select.option.other' => 'contact.form.select.option.other'),
'label' => 'contact.form.select.reason'
))
->add('send', SubmitType::class, array('label' => 'contact.form.textarea.send'));
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($default_choice) {
$form = $event->getForm();
if($default_choice == 'contact.form.select.option.information_request') {
$form->add('email', TextType::class, array(
'label' => 'contact.form.input.email',
));
$this->session->set('show_email', true);
}
if($default_choice == 'contact.form.select.option.business_membership_application') {
$form->add('emailPro', TextType::class, array(
'label' => 'contact.form.input.emailPro',
));
$form->add('company', TextType::class, array(
'label' => 'contact.form.input.company',
));
$this->session->set('show_email_pro', true);
$this->session->set('show_company', true);
}
if($default_choice == 'contact.form.select.option.registration_request') {
$form->add('companySpouse', TextType::class, array(
'label' => 'contact.form.input.companyspouse',
));
$this->session->set('show_company_spouse', true);
}
if($default_choice == 'contact.form.select.option.registration_request' || $default_choice == 'contact.form.select.option.information_request') {
$form->add('message', TextareaType::class, array(
'label' => 'contact.form.textarea.message',
));
$this->session->set('show_message', true);
}
});
}
在控制器中,处理此窗体的函数如下所示:
public function contactAction(Request $request, Mailer $mailer) {
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact, ['allow_extra_fields' => true]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mailer->sendContactMail($form);
$em = $this->getDoctrine()->getManager();
$em->persist($contact);
$em->flush();
}
return $this->render('WIVCoreBundle:Core:contact.html.twig', array(
'form' => $form->createView(),
'routes' => [
'blank' => $this->generateUrl('wiv_core_contact', ['subject' => ContactType::CONTACT_CHOICE_BLANK]),
'register' => $this->generateUrl('wiv_core_contact', ['subject' => ContactType::CONTACT_CHOICE_REGISTER]),
'company' => $this->generateUrl('wiv_core_contact', ['subject' => ContactType::CONTACT_CHOICE_COMPANY]),
'contact' => $this->generateUrl('wiv_core_contact', ['subject' => ContactType::CONTACT_CHOICE_CONTACT]),
],
'default_route' => $this->generateUrl('wiv_core_contact'),
));
}
我的问题:是否有更好的方式显示/隐藏字段?也许是一些感觉不完全混乱的东西
我不需要牵手,只要指向正确的方向。可能是我遗漏了文档的某些部分。是的,有更好的方法可以做到这一点。您可以使用表单事件修改表单的元素。还有一个食谱条目,描述了此功能: 我还强烈推荐Bernhard Schussek(该组件的创建者)的幻灯片:
我不确定是否收到您的问题,我将提供答案,如果我答错了,请随意评论
为什么不在控制器内的
联系人
实体中设置主题:
public function contactAction(Request $request, Mailer $mailer) {
$contact = new Contact();
$contact->setSubject($request->query->get('subject');
.....
}
将联系人
实体传递给表单时,表单中已经有主题字段,然后在预设数据
事件中,检查联系人
实体的主题
字段:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($default_choice) {
$form = $event->getForm();
$contact = $event->getData();
if ($contact && $contact->getSubject() == 'value1' ) {
$form->add(...)
// do your magic here
}));
}
来源:您可以使用实体(或DTO)来完成工作,而不是设置表单字段。为了更方便,您可以使用Symfony的PropertyAccess组件 大概是这样的:
public function contactAction(Request $request, Mailer $mailer)
{
$contact = new Contact();
$contact->fromArray($request->query->all());
$form = $this->createForm(ContactType::class, $contact, ['allow_extra_fields' => true]);
//...
}
class Contact
{
public function fromArray(array $properties) : void
{
$propertyAccessor = PropertyAccess::createPropertyAccessor();
foreach ($properties as $key => $value) {
if (! $propertyAccessor->isWritable($this, $key)) {
continue;
}
$propertyAccessor->setValue($this, $key, $value);
}
}
}
您的
联系人
实体有一个名为主题
的字段,类型为string right?是的,这是正确的。是的。