表单只能提交一次500内部服务器错误 - AlreadySubmittedException

时间:2016-04-26 11:10:59

标签: php forms symfony doctrine-orm dql

我正在尝试使用FOSUserBundle创建登录/注册表单。登录后,用户获得主页。其中他必须从两个单选按钮类型选项为2个时隙选择两个不同的事件并点击提交。此外,如果用户已经注册并登录,则他可以看到他之前选择的选项。他也可以改变它们。当我从控制器内部创建主页时,代码工作正常。

这是控制器代码:

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\events;
//use AppBundle\Entity\eventtype;
use AppBundle\Entity\users;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class DefaultController extends Controller {

    /**
     * @Route("/home", name="homepage")
     */
    public function indexAction(Request $request) {

        $events = new events();

        $greet = 'Welcome to the Birthday Party registration!';
        $selection1 = '';
        $selection2 = '';

        $et1 = 0;
        $et2 = 0;

         //get the events repository
        $repository = $this->getDoctrine()->getRepository('AppBundle:events');

        //get the user_id of the logged in user
        $user = $this->container->get('security.context')->getToken()->getUser();
        $events->setUser($user);
        $x = $events->getUser()->getID();

        //check if the user has already registered or not
        $y = $repository->findOneBy(array('user' => $x));

        //If the user has registered already, set the data value for the form 
        if($y){
            $et1 = $y->getET1();
            $et2 = $y->getET2();
        }

        //create form
        $form = $this->createFormBuilder($events)
                ->add('eT1', ChoiceType::class, array(
                    'choices' => array(
                        'Poker' => 1,
                        'Chess' => 2,
                        'Cricket' => 3,
                        'Marbles' => 4,
                        'Football' => 5,
                    ),
                    'choices_as_values' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Choose After Breakfast Event',
                    'data' => $et1
                ))
                ->add('eT2', ChoiceType::class, array(
                    'choices' => array(
                        'Poker' => 1,
                        'Chess' => 2,
                        'Cricket' => 3,
                        'Marbles' => 4,
                        'Football' => 5,
                    ),
                    'choices_as_values' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Choose After Snacks Event',
                    'data' => $et2
                ))
                ->add('save', SubmitType::class, array('label' => 'Submit'))
                ->getForm();

        //retrieve the choices array for eT1 and eT2
        $eT1Choices = $form->get('eT1')->getConfig()->getOption('choices');
        $eT2Choices = $form->get('eT2')->getConfig()->getOption('choices');

        //intialize the eventname variables
        $eT1Name = '';
        $eT2Name = '';

        if ($y) {

            //If the user has registered already, display his previously selected options
            $selection1 = 'Your After Breakfast event:';
            $selection2 = 'Your After Snacks event:';

            //set the eventname based on the value of et1
            foreach ($eT1Choices as $key => $value) {
                if ($et1 == $value) {
                    $eT1Name = $key;
                }
            }

            //set the eventname based on the value of et2
            foreach ($eT2Choices as $key => $value) {
                if ($et2 == $value) {
                    $eT2Name = $key;
                }
            }
        }

        //after submission
        if ($request->isMethod('POST')) {
            $form->submit($request);

            //retrieve maxlimit parameters from parameters.yml
            $maxPoker = $this->container->getParameter('pokermaxlimit');
            $maxChess = $this->container->getParameter('chessmaxlimit');
            $maxCricket = $this->container->getParameter('cricketmaxlimit');
            $maxMarbles = $this->container->getParameter('marblesmaxlimit');
            $maxFootball = $this->container->getParameter('footballmaxlimit');

            //initialize $eventMaxLim
            $eventMaxLim = 0;

            //retrieve form data
            $formData = $form->getData();

            $ET1 = $formData->getET1();
            $ET2 = $formData->getET2();

            $selection1 = 'Your After Breakfast event:';
            $selection2 = 'Your After Snacks event:';

            //set the eventname based on the value of eT1
            foreach ($eT1Choices as $key => $value) {
                if ($ET1 == $value) {
                    $eT1Name = $key;
                }
            }

            //set the eventname based on the value of eT2
            foreach ($eT2Choices as $key => $value) {
                if ($ET2 == $value) {
                    $eT2Name = $key;
                }
            }

            //check to see if the user has registered the same event for eT1 and eT2
            if ($ET1 == $ET2) {
                $this->get('session')->getFlashBag()->set('error', 'You have chosen same events for both time slots! Please choose different ones.');
            }

            //check to see how many users have registered for the opted event(eT1)
            $query1 = $repository->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.eT1 = :eT1')
                    ->setParameter('eT1', $ET1)
                    ->getQuery();
            $a = $query1->getSingleScalarResult();

            //set the $eventMaxLim based on the chosen event for eT1
            if ($ET1 == 1) {
                $eventMaxLim = $maxPoker;
            } else if ($ET1 == 2) {
                $eventMaxLim = $maxChess;
            } else if ($ET1 == 3) {
                $eventMaxLim = $maxCricket;
            } else if ($ET1 == 4) {
                $eventMaxLim = $maxMarbles;
            } else if ($ET1 == 5) {
                $eventMaxLim = $maxFootball;
            }

            //check to see if the after breakfast event (eT1) is full (ie.has reached the maxlimit)
            if ($a >= $eventMaxLim) {
                $this->get('session')->getFlashBag()->set('error', 'choose another After Breakfast event, this one is full');
            }

            //check to see how many users have registered for the opted event(eT2)
            $query2 = $repository->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.eT2 = :eT2')
                    ->setParameter('eT2', $ET2)
                    ->getQuery();
            $b = $query2->getSingleScalarResult();

            //set the $eventMaxLim based on the chosen event for eT2
            if ($ET2 == 1) {
                $eventMaxLim = $maxPoker;
            } else if ($ET2 == 2) {
                $eventMaxLim = $maxChess;
            } else if ($ET2 == 3) {
                $eventMaxLim = $maxCricket;
            } else if ($ET2 == 4) {
                $eventMaxLim = $maxMarbles;
            } else if ($ET2 == 5) {
                $eventMaxLim = $maxFootball;
            }

            //check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
            if ($b >= $eventMaxLim) {
                $this->get('session')->getFlashBag()->set('error', 'choose another After Snacks event, this one is full');
            }

            if (($a < $eventMaxLim) && ($b < $eventMaxLim) && ($ET1 != $ET2)) {
                if ($form->isValid()) {

                    //get the entity manager
                    $em = $this->getDoctrine()->getManager();

                    // If the user is registering for the first time (execute the Insert query)
                    if (!$y) {
                        $em->persist($events);
                        $em->flush();
                        //return $this->redirectToRoute('homepage');
                    }

                    //If the user has registered already and want change his registered events (execute the Update query)
                    else {
                        $y->setET1($ET1);
                        $y->setET2($ET2);
                        $em->persist($y);
                        $em->flush();
                        //return $this->redirectToRoute('homepage');
                    }
                }
            }
        }

        return $this->render('default/index.html.twig', array(
                    'form' => $form->createView(),
                    'greet' => $greet,
                    'selection1' => $selection1,
                    'eT1Name' => $eT1Name,
                    'selection2' => $selection2,
                    'eT2Name' => $eT2Name,
        ));
    }

}

以下是事件实体:

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
//use Symfony\Component\Validator\Constraints as Assert;

/**
 * events
 *
 * @ORM\Table(name="events")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\eventsRepository")
 */
class events {

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var int
     *
     * @ORM\Column(name="ET1", type="integer")
     */
    protected $eT1;

    /**
     * @var int
     *
     * @ORM\Column(name="ET2", type="integer")
     */
    protected $eT2;

    /**
     * @ORM\OneToOne(targetEntity="users", inversedBy="event")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
        protected $user;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId() {
        return $this->id;
    }

    /**
     * Set user
     *
     * @param users $user
     * @return events
     */
    public function setUser($user) {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return events
     */
    public function getUser() {
        return $this->user;
    }


    /**
     * Set eT1
     *
     * @param integer $eT1
     * @return events
     */
    public function setET1($eT1) {
        $this->eT1 = $eT1;

        return $this;
    }

    /**
     * Get eT1
     *
     * @return integer 
     */
    public function getET1() {
        return $this->eT1;
    }

    /**
     * Set eT2
     *
     * @param integer $eT2
     * @return events
     */
    public function setET2($eT2) {
        $this->eT2 = $eT2;

        return $this;
    }

    /**
     * Get eT2
     *
     * @return integer 
     */
    public function getET2() {
        return $this->eT2;
    }

}

但是当我在eventsType.php中移动表单创建的代码时,出现了以下错误 - 表单只能提交一次500内部服务器错误 - AlreadySubmittedException 这是新的控制器代码:

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\events;
use AppBundle\Form\eventsType;
use AppBundle\Entity\users;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class DefaultController extends Controller {

    /**
     * @Route("/home", name="homepage")
     */
    public function indexAction(Request $request) {

        $greet = 'Welcome to the Birthday Party registration!';
        $selection1 = '';
        $selection2 = '';

        //get the events repository
        $repository = $this->getDoctrine()->getRepository('AppBundle:events');

        //get the user_id of the logged in user
        $user = $this->container->get('security.context')->getToken()->getUser()->getID();

        //check if the user has already registered or not
        $regEvents = $repository->findOneBy(array('user' => $user));

        $events = new events();

        //create form
        $form = $this->createForm(new \AppBundle\Form\eventsType($regEvents), $events);

        $form->handleRequest($request);

        //retrieve the choices array for eT1 and eT2
        $eT1Choices = $form->get('eT1')->getConfig()->getOption('choices');
        $eT2Choices = $form->get('eT2')->getConfig()->getOption('choices');

        //intialize the eventname variables
        $eT1Name = '';
        $eT2Name = '';

        if ($regEvents) {

            $et1 = $regEvents->getET1();
            $et2 = $regEvents->getET2();

            //If the user has registered already, display his previously selected options
            $selection1 = 'Your After Breakfast event:';
            $selection2 = 'Your After Snacks event:';

            //set the eventname based on the value of et1
            foreach ($eT1Choices as $key => $value) {
                if ($et1 == $value) {
                    $eT1Name = $key;
                }
            }

            //set the eventname based on the value of et2
            foreach ($eT2Choices as $key => $value) {
                if ($et2 == $value) {
                    $eT2Name = $key;
                }
            }
        }

        //after submission
        if ($request->isMethod('POST')) {
            $form->submit($request);

            //First check the value entered by the user
            if ($events->getET1() == null || $events->getET2() == null) {
                //User did not choose both the events
                $this->container->get('session')->getFlashBag()->add('error', 'Oh oh! It is mandatory to choose an option for all the events');
                //return array('form' => $form->createView());
            }

            //retrieve maxlimit parameters from parameters.yml
            $maxPoker = $this->container->getParameter('pokermaxlimit');
            $maxChess = $this->container->getParameter('chessmaxlimit');
            $maxCricket = $this->container->getParameter('cricketmaxlimit');
            $maxMarbles = $this->container->getParameter('marblesmaxlimit');
            $maxFootball = $this->container->getParameter('footballmaxlimit');

            //initialize $eventMaxLim
            $eventMaxLim1 = 0;
            $eventMaxLim2 = 0;

            //retrieve form data
            $formData = $form->getData();

            $ET1 = $formData->getET1();
            $ET2 = $formData->getET2();

            $selection1 = 'Your After Breakfast event:';
            $selection2 = 'Your After Snacks event:';

            //set the eventname based on the value of eT1
            foreach ($eT1Choices as $key => $value) {
                if ($ET1 == $value) {
                    $eT1Name = $key;
                }
            }

            //set the eventname based on the value of eT2
            foreach ($eT2Choices as $key => $value) {
                if ($ET2 == $value) {
                    $eT2Name = $key;
                }
            }

            //check to see if the user has registered the same event for eT1 and eT2
            if ($ET1 == $ET2) {
                $this->get('session')->getFlashBag()->set('error', 'You have chosen same events for both time slots! Please choose different ones.');
            }

            //check to see how many users have registered for the opted event(eT1)
            $query1 = $repository->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.eT1 = :eT1')
                    ->setParameter('eT1', $ET1)
                    ->getQuery();
            $a = $query1->getSingleScalarResult();

            //set the $eventMaxLim based on the chosen event for eT1
            if ($ET1 == 1) {
                $eventMaxLim1 = $maxPoker;
            } else if ($ET1 == 2) {
                $eventMaxLim1 = $maxChess;
            } else if ($ET1 == 3) {
                $eventMaxLim1 = $maxCricket;
            } else if ($ET1 == 4) {
                $eventMaxLim1 = $maxMarbles;
            } else if ($ET1 == 5) {
                $eventMaxLim1 = $maxFootball;
            }

//            var_dump($eventMaxLim1);
//            exit;
            //check to see if the after breakfast event (eT1) is full (ie.has reached the maxlimit)
            if ($a >= $eventMaxLim1) {
                $this->get('session')->getFlashBag()->set('error', 'choose another After Breakfast event, this one is full');
            }

            //check to see how many users have registered for the opted event(eT2)
            $query2 = $repository->createQueryBuilder('p')
                    ->select('count(p)')
                    ->where('p.eT2 = :eT2')
                    ->setParameter('eT2', $ET2)
                    ->getQuery();
            $b = $query2->getSingleScalarResult();

            //set the $eventMaxLim based on the chosen event for eT2
            if ($ET2 == 1) {
                $eventMaxLim2 = $maxPoker;
            } else if ($ET2 == 2) {
                $eventMaxLim2 = $maxChess;
            } else if ($ET2 == 3) {
                $eventMaxLim2 = $maxCricket;
            } else if ($ET2 == 4) {
                $eventMaxLim2 = $maxMarbles;
            } else if ($ET2 == 5) {
                $eventMaxLim2 = $maxFootball;
            }

            //check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
            if ($b >= $eventMaxLim2) {
                $this->get('session')->getFlashBag()->set('error', 'choose another After Snacks event, this one is full');
            }

            if (($a < $eventMaxLim1) && ($b < $eventMaxLim2) && ($ET1 != $ET2) && ($events->getET1() == null ||
                    $events->getET2() == null)) {
                if ($form->isValid()) {

                    //get the entity manager
                    $em = $this->getDoctrine()->getManager();

                    // If the user is registering for the first time (execute the Insert query)
                    if (!$regEvents) {
                        $events->setUser($user);
                        $events->setET1($ET1);
                        $events->setET2($ET2);
                        $em->persist($events);
                        $em->flush();
                        //return $this->redirectToRoute('homepage');
                    }

                    //If the user has registered already and want change his registered events (execute the Update query)
                    else {
                        $events->setET1($ET1);
                        $events->setET2($ET2);
                        $em->persist($events);
                        $em->flush();
                        //return $this->redirectToRoute('homepage');
                    }
                }
            }
        }

        return $this->render('default/index.html.twig', array(
                    'form' => $form->createView(),
                    'greet' => $greet,
                    'selection1' => $selection1,
                    'eT1Name' => $eT1Name,
                    'selection2' => $selection2,
                    'eT2Name' => $eT2Name,
        ));
    }

}

下面是eventsType.php:

<?php 

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class eventsType extends AbstractType {

    protected $events;

    public function __construct($events) {
        $this->events = $events;
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {

            if (!empty($this->events)){
           if($this->events->getET1() == null){
                $et1 = '';   
           }
           else {
               $et1 = $this->events->getET1();
           }
           if($this->events->getET2() == null){
                $et2 = '';   
           }
           else {
               $et2 = $this->events->getET2();
           }
            }
            else {
           $et1 = '';
           $et2 = '';
            }

        $builder->add('eT1', ChoiceType::class, array(
                    'choices' => array(
                        'Poker' => 1,
                        'Chess' => 2,
                        'Cricket' => 3,
                        'Marbles' => 4,
                        'Football' => 5,
                    ),
                    'choices_as_values' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Choose After Breakfast Event',
                    'data' => $et1,
//                    'mapped' => $map1,
                ))
                ->add('eT2', ChoiceType::class, array(
                    'choices' => array(
                        'Poker' => 1,
                        'Chess' => 2,
                        'Cricket' => 3,
                        'Marbles' => 4,
                        'Football' => 5,
                    ),
                    'choices_as_values' => true,
                    'expanded' => true,
                    'multiple' => false,
                    'label' => 'Choose After Snacks Event',
                    'data' => $et2,
//                    'mapped' => $map2,
                ))
                ->add('save', SubmitType::class, array('label' => 'Submit'));
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\events',
        ));
    }

}

1 个答案:

答案 0 :(得分:1)

从您的代码中删除$form->submit($request);,这应该会停止此错误消息。

$form->submit($request);(现已弃用)用于从您的控制器提交表单,如果您正在使用 $form->handleRequest($request);$form->submit($request);一旦用户按下提交按钮submit(),就会再次尝试提交表单,因此错误消息“表单只能提交一次link to docs

旁注:

if ($events->getET1() == null || $events->getET2() == null) {
    //User did not choose both the events
    $this->container->get('session')->getFlashBag()->add('error', 'msg');
     //return array('form' => $form->createView());
}

如果条件可以而且应该被断言docs替换,虽然flash消息很棒且非常有用,但这不是使用它的地方,你可能误解了它的用法,它用于显示成功表单提交后的失败消息,而不是验证消息,我们有断言消息

并阅读有关MVC模式和“关注点分离”的内容,将代码划分为多个部分,一个代码向用户显示内容,一个与数据库交互,一个执行所有逻辑处理,控制器为绝对不是做这些的地方。控制器在大多数时候必须很小,并且必须使用框架的内置功能。<​​/ p>

我建议暂时不要编写代码并开始阅读有关软件架构和设计模式的内容,以当前的方式我看不到很多进展空间

-dheeraj