【问题标题】:Symfony: Form should not contain extra fields with two forms on one pageSymfony:表单不应包含额外字段,一页上有两个表单
【发布时间】:2018-09-02 11:36:09
【问题描述】:

我是 Symfony 3 的新手,我正在尝试构建一个页面,其中我有两个不同实体的两个表单。一个用于添加愿望,一个用于添加评论。 当我提交一个表单时,第二个会给出错误“此表单不应包含额外字段”。

我试过 $form->get('submit')->isClicked() 但没用。

我也尝试了allow_extra_fields => true,然后我收到了错误,尽管我提交了评论,但它试图插入一个愿望。此外,在尝试进行查询之前,我使用 form->isValid() 来检查表单是否有效。

它怎么可能同时提交两个表单?

这是我的控制器:

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Shaker\JRQBundle\Entity\Wish;
use Shaker\JRQBundle\Entity\User;
use Shaker\JRQBundle\Entity\Wishcom;
use Shaker\JRQBundle\Entity\Wishsol;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

class HomeController extends Controller
{
public function wishAction (Request $request, $id) {
        $wish=$this->getWish($id);
        $arraywishcom=$this->getWishComs($wish);
        $arraywishsol=$this->getWishSols($wish);

        $wishcom = new Wishcom(); 
        $wishsol = new Wishsol();

        $formcom=$this->buildFormCom($wishcom);
        $formsol=$this->buildFormSol($wishsol);

            // store a comment or a solution
             if ($request->isMethod('POST')) {

                $formcom->handleRequest($request);

                if ($formcom->isValid()) {
                    $em=$this->getDoctrine()->getManager();
                    $security = $this->container->get('security.token_storage');
                    $token=$security->getToken();
                    $user=$token->getUser();
                    $wishcom->setUser($user);
                    $wishcom->setWish($wish);
                    $em->persist($wishcom);
                    $em->flush();
                    $request->getSession()->getFlashBag()->add('notice', "Commentaire bien enregistré.");
                }

             $formsol->handleRequest($request);

                if ($formsol->isValid()) {
                    $em=$this->getDoctrine()->getManager();
                    $security = $this->container->get('security.token_storage');
                    $token=$security->getToken();
                    $user=$token->getUser();
                    $wishsol->setUser($user);
                    $wishsol->setWish($wish);
                    $em->persist($wishsol);
                    $em->flush();
                    $request->getSession()->getFlashBag()->add('notice', "Solution bien enregistrée.");
                }

            }

        return $this->render('ShakerJRQBundle:Home:wish.html.twig', array(
            'wish' => $wish,
            'formcom' => $formcom->createView(),
            'formsol' => $formsol->createView(),
            'wishcom' => $arraywishcom,
            'wishsol' => $arraywishsol));
    }
private function buildFormCom (Wishcom $wishcom) {
      //build the form for discussing the topic
        $formbuilder = $this->get('form.factory')->CreateBuilder(FormType::class, $wishcom, array('allow_extra_fields' => true));
        $formbuilder
            ->add('Type', ChoiceType::class, array(
                'choices'  => array(
                'Argument' => 'Argument',
                'Contre-argument' => 'Contre-argument',
                'Commentaire' => 'Commentaire')))
            ->add('Comment', TextareaType::class)
            ->add('Commenter', SubmitType::class);

            $formcom=$formbuilder->getForm();
            return $formcom;
}

private function buildFormSol (Wishsol $wishsol) {
      //build the form for adding a solution        
        $formbuilder = $this->get('form.factory')->CreateBuilder(FormType::class, $wishsol, array('allow_extra_fields' => true));
        $formbuilder
            ->add('Solution', TextareaType::class)
            ->add('Proposer une solution', SubmitType::class);

        $formsol=$formbuilder->getForm();
        return $formsol;
        }
}

【问题讨论】:

    标签: forms symfony


    【解决方案1】:

    从常识的角度来看,这不应该发生。但是,如果您查看生成的标记(在提交之前),您可能会看到您的表单名为 form,而您的字段名为 form[Comment]form[Type] 等。请注意,两个表单的字段都有一个 @ 987654324@ 前缀。

    命名冲突使Symfony 认为您将要提交这两个表单。您有两种方法可以解决此问题:

    1.让您的表单提交到不同的 URL,并在完成后重定向到常用的 URL。

    这涉及向您的两个表单构建器添加setAction 调用。在某些情况下,这可能正是您想要的,但如果您的公共代码(提交后的那个)依赖于大部分以形式出现的东西,这只是痛苦。例如:

    $formbuilder = $this->get('form.factory')
        ->createBuilder(FormType::class, $wishcom);
    
    $formbuilder
        ->add('Type', ChoiceType::class, array(
            'choices'  => array(
                'Argument' => 'Argument',
                'Contre-argument' => 'Contre-argument',
                'Commentaire' => 'Commentaire')
            )
        )
        ->add('Comment', TextareaType::class)
        ->add('Commenter', SubmitType::class)
        ->setAction('/formcom-submit') // <-- THIS
    
    $formcom=$formbuilder->getForm();
    

    2。创建一个named 表单构建器。

    这是 IMO 更自然的处理表单命名冲突的方式。每个表格都有自己的名称,因此当您调用handleRequest 时,只有一个表格将被“处理”。例如:

    $formbuilder = $this->get('form.factory')
        ->createNamedBuilder('formcom', FormType::class, $wishcom);
    

    和:

    $formbuilder = $this->get('form.factory')
        ->createNameBuilder('formsol', FormType::class, $wishsol);
    

    另一件值得研究的事情是您是否应该将这两个表单移到单独的类中。在这种情况下,您将获得开箱即用的名称唯一性,并且您的代码肯定会感觉更干净。无论如何,如果您打算在不同的操作中重复使用此表单,我会说去吧。

    希望这会有所帮助...

    【讨论】:

    • 非常感谢您快速提供有用的答案!我使用 createNamedBuilder 方法。由于我没有使用此页面之外的表格,因此我没有考虑过使用它们制作课程。但是谢谢你的提示!
    • 很高兴我能帮上忙 ;)
    • 非常感谢。我不知道为什么 Symfonys 的创建者隐藏了这个方法......我刚刚检查过:createBuilder -> 347k 的结果(symfony.com 上的 64 个) createNamedBuilder -> 不到 10k 的结果(symfony.com 上的 6 个)
    猜你喜欢
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    相关资源
    最近更新 更多