Symfony: форма не должна содержать лишних полей с двумя формами на одной странице - PullRequest
0 голосов
/ 02 сентября 2018

Я новичок в 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 голосов
/ 02 сентября 2018

С точки зрения здравого смысла этого не должно было случиться. Однако, если вы посмотрите на сгенерированную разметку (перед отправкой), вы, вероятно, увидите, что ваша форма имеет имя form, а ваши поля - form[Comment], form[Type] и т. Д. Обратите внимание, что поле обеих форм будет иметь form префикс.

Конфликт имен - это то, что заставляет Symfony думать, что вы собираетесь отправить обе формы. У вас есть два способа решения этой проблемы:

1. Сделайте так, чтобы ваши формы отправлялись по другому 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);

Еще одна вещь, которую стоит изучить, стоит ли переносить обе формы в отдельные классы. В этом случае вы получите уникальность имени из коробки, и ваш код наверняка будет чувствовать себя чище. В любом случае, если вы собираетесь повторно использовать эту форму в другом действии, я бы сказал, пойти на это.

Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...