一个表单只能提交一次 500 Internal Server Error - AlreadySubmittedException
A form can only be submitted once 500 Internal Server Error - AlreadySubmittedException
我正在尝试使用 FOSUserBundle 创建一个 login/registration 表单。登录后,用户将获得一个主页。其中他必须从两个单选按钮类型选项中为 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 Internal Server Error - 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',
));
}
}
从您的代码中删除 $form->submit($request);
,这应该会停止此错误消息。
$form->submit($request);
(现已弃用)用于从您的控制器提交表单,在您使用的情况下
$form->handleRequest($request);
AND $form->submit($request);
所以一旦用户按下提交按钮 submit() is called which again attempts to submit the form and hence the error message "A form can only be submitted once" 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());
}
这个 if 条件可以而且应该被断言替换 docs 虽然 flash 消息很棒而且非常有用,但这不是使用它的地方,您可能误解了它的用法,它曾经用于在提交表单后显示成功和失败消息,而不是验证消息,我们有断言消息
并阅读 MVC 模式和 'separation of concerns',将您的代码分成几部分,一个包含向用户显示内容的代码,一个与您的数据库交互的代码,一个执行所有逻辑处理的代码, controller 绝对不是做这些的地方。大多数时候控制器必须很小,并且必须利用框架的内置功能。
我建议从编写代码中休息一下,开始阅读有关软件架构和设计模式的内容,以目前的方式我看不到太多 space 进步
-dheeraj
我正在尝试使用 FOSUserBundle 创建一个 login/registration 表单。登录后,用户将获得一个主页。其中他必须从两个单选按钮类型选项中为 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 Internal Server Error - 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',
));
}
}
从您的代码中删除 $form->submit($request);
,这应该会停止此错误消息。
$form->submit($request);
(现已弃用)用于从您的控制器提交表单,在您使用的情况下
$form->handleRequest($request);
AND $form->submit($request);
所以一旦用户按下提交按钮 submit() is called which again attempts to submit the form and hence the error message "A form can only be submitted once" 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());
}
这个 if 条件可以而且应该被断言替换 docs 虽然 flash 消息很棒而且非常有用,但这不是使用它的地方,您可能误解了它的用法,它曾经用于在提交表单后显示成功和失败消息,而不是验证消息,我们有断言消息
并阅读 MVC 模式和 'separation of concerns',将您的代码分成几部分,一个包含向用户显示内容的代码,一个与您的数据库交互的代码,一个执行所有逻辑处理的代码, controller 绝对不是做这些的地方。大多数时候控制器必须很小,并且必须利用框架的内置功能。
我建议从编写代码中休息一下,开始阅读有关软件架构和设计模式的内容,以目前的方式我看不到太多 space 进步
-dheeraj