2016-04-26 53 views
-2

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

这里是控制器代码:

<?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

请注意,而不是有更好的反应是只使用相关标签和理解你的问题所需的最小代码。发布的代码无法帮助其他读者遇到同样的问题。 – goto

+0

关于标签,我想我在这里使用了我的代码中的所有标签。代码,是的,下次我会尽量保持它的短。 – utkarsh2k2

回答

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()); 
} 

这一点,如果条件罐和sh应该被断言docs取代,虽然Flash消息很棒并且非常有用,但这不是使用它的地方,您可能误解了它的用法,它在表单提交后用于显示成功和失败消息,而不用于验证消息,我们提出了关于该代码的消息

并且还阅读了有关MVC模式和“关注点分离”的内容,将代码划分为多个部分,其中一个代码向用户显示内容,一个与数据库交互,一个执行所有操作逻辑处理,控制器绝对不是做这些任何事情的地方。控制器在大部分时间内必须很小,并且必须利用框架的内置功能。

我会建议从写代码稍事休息,并开始阅读有关软件架构和设计模式,与目前的方式,我没有看到太多的空间进步

-dheeraj

+1

谢谢dheeraj。答案很恰当。我将尝试更多地阅读关于MVC和分离问题的更多信息 – utkarsh2k2