Symfony:表单不应在一页上包含两个表单的额外字段

时间:2018-09-02 11:36:09

标签: forms symfony

我是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;
        }
}

1 个答案:

答案 0 :(得分:2)

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

命名冲突是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);

值得研究的另一件事是,是否应该将两种形式都移到单独的类中。在这种情况下,您将获得开箱即用的名称唯一性,并且您的代码肯定会更加干净。无论如何,如果您打算以其他方式重复使用此表单,我会说的去做。

希望这对您有帮助...