Я строю викторину. При нажатии на кнопку для каждого ответа вызывается функция ajax, которая возвращает ответ Json, который перезагружает текущий маршрут, чтобы отобразить следующий вопрос или результаты теста, если он завершен.
Пользователь может повторить новый тест, если ему это не удалось, и может повторить, пока не добьется успеха.
Для этого он нажимает на форму ввода на странице результатов.
Моя проблема в том, что при первом отображении результатов все в порядке. Я нажимаю на кнопку «Отправить повтор», чтобы перезапустить новую форму. Я удаляю параметр поста 'retry'. И все же, он возвращается после следующего вызова AJAX.
Может ли кто-нибудь объяснить мне, что происходит и как удалить параметр post навсегда?
Мой контроллер:
класс ExamController расширяет контроллер {
/**
* Return ExamTaker views
*/
public function indexAction(Request $request, $id){
// get current user
$user = $this->getUser();
// get manager
$em = $this->getDoctrine()->getManager();
// get user stats service
$stats = $this->get('user.stats');
/*************************************/
/* Get usefull datas */
/*************************************/
// get current module group
$module_group = $em->getRepository('UserBundle:ModuleGroup')->findOneById($id);
// check if module group taker exists
$module_group_taker = $this->getDoctrine()->getRepository('UserBundle:ModuleGroupTaker')->findOneBy(array('user' => $user, 'module_group'=>$module_group));
// check if an exam taker is not completed yet
$current_exam_taker = $em->getRepository('UserBundle:ExamTaker')->findOneBy(array('user' => $user, 'module_group' => $module_group, 'completed' => null));
// check if exam is already succeed
$exam_certif_taker = $em->getRepository('UserBundle:ExamCertificationTaker')->findOneBy(array('user' => $user, 'module_group' => $module_group));
// check if an exam is in correction state
$exam_taker_in_correction = $em->getRepository('UserBundle:ExamTaker')->getExamInCorrection($user, $module_group);
/**************************************/
/* Security : access not allowed to */
/* expired supervisor */
/**************************************/
$ac = $this->get('security.authorization_checker');
if (($ac->isGranted('ROLE_SUPERVISOR') || $ac->isGranted('ROLE_MANAGER')) && $user->getExpiration()->format('YmdHis') < date('YmdHis')) {
throw $this->createAccessDeniedException();
}
/********************************************/
/* if user already succeed with score 20/20 */
/********************************************/
if($exam_certif_taker && $exam_certif_taker->getExamTaker()->getScore() == 20){
dump('1');
// return results view
return $this->render('UserBundle:exam:examresults.html.twig', array(
'exam' => $exam_certif_taker->getExamTaker(),
'exam_certif' => $exam_certif_taker,
'certification' => $user->getCertification()
));
}
/********************************************/
/* if user already succeed with less than */
/* 20/20 and wants to retry */
/********************************************/
else if($exam_certif_taker && $exam_certif_taker->getTries() == 1 && $request->request->get('retry') && !$user->getCertification()){
dump('2');
$request->request->remove('retry');
$request->request->setContent(null);
$exam_taker_in_correction->setCorrected(new \DateTime());
$exam_taker = $this->createNewExamTaker($user, $module_group);
$next_question = $this->prepareNextExamQuestion(1, $exam_taker);
return $this->render('UserBundle:exam:exam.html.twig', array(
'size' => count($exam_taker->getQuestions()),
'title' => $module_group->getTitle(),
'question' => $next_question,
'color' => $module_group->getColor(),
'exam_taker' => $exam_taker
));
}
/********************************************/
/* if user already succeed with less than */
/* 20/20 and an exam taker is not completed */
/********************************************/
else if($exam_certif_taker && $current_exam_taker){
dump('3');
$next_exam_answer_taker = $em->getRepository('UserBundle:ExamAnswerTaker')->findOneBy(array('exam' => $current_exam_taker, 'answer' => null));
$next_question = $next_exam_answer_taker->getQuestion();
return $this->render('UserBundle:exam:exam.html.twig', array(
'size' => count($current_exam_taker->getQuestions()),
'title' => $module_group->getTitle(),
'question' => $next_question,
'color' => $module_group->getColor(),
'exam_taker' => $current_exam_taker
));
}
/********************************************/
/* for all other cases user has succeed */
/* return results */
/********************************************/
else if($exam_certif_taker){
dump('4');
// return results view
return $this->render('UserBundle:exam:examresults.html.twig', array(
'exam' => $exam_certif_taker->getExamTaker(),
'exam_certif' => $exam_certif_taker,
'certification' => $user->getCertification()
));
}
/********************************************/
/* if user failed and wants to retry */
/********************************************/
else if($exam_taker_in_correction && $request->request->get('retry')){
dump('5');
$request->request->remove('retry');
$exam_taker_in_correction->setCorrected(new \DateTime());
$exam_taker = $this->createNewExamTaker($user, $module_group);
$next_question = $this->prepareNextExamQuestion(1, $exam_taker);
return $this->render('UserBundle:exam:exam.html.twig', array(
'size' => count($exam_taker->getQuestions()),
'title' => $module_group->getTitle(),
'question' => $next_question,
'color' => $module_group->getColor(),
'exam_taker' => $exam_taker
));
}
/********************************************/
/* if user failed and didn't ask to retry */
/********************************************/
else if($exam_taker_in_correction){
dump('6');
// return results view
return $this->render('UserBundle:exam:examresults.html.twig', array(
'exam' => $exam_taker_in_correction,
'exam_certif' => false,
'certification' => false
));
}
/********************************************/
/* if an exam is not completed yet */
/********************************************/
else if($current_exam_taker){
dump('7');
$next_exam_answer_taker = $em->getRepository('UserBundle:ExamAnswerTaker')->findOneBy(array('exam' => $current_exam_taker, 'answer' => null));
$next_question = $next_exam_answer_taker->getQuestion();
return $this->render('UserBundle:exam:exam.html.twig', array(
'size' => count($current_exam_taker->getQuestions()),
'title' => $module_group->getTitle(),
'question' => $next_question,
'color' => $module_group->getColor(),
'exam_taker' => $current_exam_taker
));
}
/********************************************/
/* all other cases, create a new exam taker */
/********************************************/
else {
dump('8');
$exam_taker = $this->createNewExamTaker($user, $module_group);
$next_question = $this->prepareNextExamQuestion(1, $exam_taker);
return $this->render('UserBundle:exam:exam.html.twig', array(
'size' => count($exam_taker->getQuestions()),
'title' => $module_group->getTitle(),
'question' => $next_question,
'color' => $module_group->getColor(),
'exam_taker' => $exam_taker
));
}
}
/**
* ajax function to save current answer
* and return either results or next question
*/
function saveAction(Request $request){
//Prepare usefull datas
$em = $this->getDoctrine()->getManager();
$exam_taker_id = $request->request->get('exam_taker_id');
$current_question_id = $request->request->get('question_id');
$answer_id = $request->request->get('answer_id');
$exam_taker = $em->getRepository('UserBundle:ExamTaker')->findOneById($exam_taker_id);
$current_question = $em->getRepository('UserBundle:ExamQuestion')->findOneById($current_question_id);
$exam_answer = $em->getRepository('UserBundle:ExamAnswer')->findOneById($answer_id);
$exam_answer_taker = $em->getRepository('UserBundle:ExamAnswerTaker')->findOneBy(array('exam'=> $exam_taker, 'question' => $current_question));
$level = $current_question->getLevel();
$next_question = false;
$module_group = $exam_taker->getModuleGroup();
$user = $exam_taker->getUser();
//save answer taker
$exam_answer_taker->setAnswer($exam_answer);
$em->flush();
// get array of exam taker questions already displayed
$exam_taker_questions = $exam_taker->getQuestions();
$count_questions = count($exam_taker_questions);
// Check if last answer is good
$good_answer = $em->getRepository('UserBundle:ExamAnswer')->findOneBy(array('question' => $current_question, 'correct' => true));
($good_answer === $exam_answer_taker->getAnswer()) ? $check_answer = true : $check_answer = false;
// update correct var
if($check_answer){
$exam_answer_taker->setCorrect(1);
} else {
$exam_answer_taker->setCorrect(0);
}
// Update last answer given
$em->flush();
// count answers group by level
$array_answers = array(
'1' => array('success' => 0, 'fail' => 0),
'2' => array('success' => 0, 'fail' => 0),
'3' => array('success' => 0, 'fail' => 0),
'4' => array('success' => 0, 'fail' => 0),
'5' => array('success' => 0, 'fail' => 0)
);
foreach ($exam_taker->getAnswers() as $answer) {
if($answer->getCorrect()){
switch ($answer->getQuestion()->getLevel()) {
case '1':
$array_answers['1']['success'] += 1;
break;
case '2':
$array_answers['2']['success'] += 1;
break;
case '3':
$array_answers['3']['success'] += 1;
break;
case '4':
$array_answers['4']['success'] += 1;
break;
case '5':
$array_answers['5']['success'] += 1;
break;
}
} else {
switch ($answer->getQuestion()->getLevel()) {
case '1':
$array_answers['1']['fail'] += 1;
break;
case '2':
$array_answers['2']['fail'] += 1;
break;
case '3':
$array_answers['3']['fail'] += 1;
break;
case '4':
$array_answers['4']['fail'] += 1;
break;
case '5':
$array_answers['5']['fail'] += 1;
break;
}
}
}
// if count questions is 20
if($count_questions == 20){
// set completed to end current exam
$exam_taker->setCompleted(new \DateTime());
// check if good answer to the current question
if($check_answer){
// set score depending on successes
if($array_answers['5']['success'] == 3){ // if 3 success level 5, set score to 20
$exam_taker->setScore(20);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($array_answers['4']['success'] == 3){ // if 3 success level 4, set score to 16
$exam_taker->setScore(16);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($array_answers['3']['success'] == 3){ // if 3 success level 3, set score to 14
$exam_taker->setScore(14);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($array_answers['2']['success'] == 3){ // if success level 2, set score to 12
$exam_taker->setScore(12);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$exam_taker->setScore(0);
}
} else {
switch ($level) {
case 5:
if($array_answers['5']['fail'] == 2){ // if 2 fail level 5, set score to 16
$exam_taker->setScore(16);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($array_answers['4']['fail'] == 3){ // if 3 fail level 4, set score 14
$exam_taker->setScore(14);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($array_answers['3']['fail'] == 3){ // if 3 fail level 3, set score 12
$exam_taker->setScore(12);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$exam_taker->setScore(0);
}
break;
case 4:
if($array_answers['4']['fail'] == 3){ // if 3 fail level 4, set score 14
$exam_taker->setScore(14);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($array_answers['3']['fail'] == 3){ // if 3 fail level 3, set score 12
$exam_taker->setScore(12);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$exam_taker->setScore(0);
}
break;
case 3:
if($array_answers['3']['fail'] == 3){ // if 3 fail level 3, set score 12
$exam_taker->setScore(12);
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$exam_taker->setScore(0);
}
break;
case 2:
$exam_taker->setScore(0);
break;
case 1:
$exam_taker->setScore(0);
break;
}
}
} else { // if not 20 questions yet
// check if good answer to the current question
if($check_answer){
if(($level == 5) && ($array_answers['5']['success'] == 3)){
$exam_taker->setScore(20);
$exam_taker->setCompleted(new \DateTime());
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else if($level == 5){
$next_question = $this->prepareNextExamQuestion(5, $exam_taker);
} else if($level == 4){
$next_question = $this->prepareNextExamQuestion(5, $exam_taker);
} else if($level == 3){
$next_question = $this->prepareNextExamQuestion(4, $exam_taker);
} else if($level == 2){
$next_question = $this->prepareNextExamQuestion(3, $exam_taker);
} else if($level == 1){
$next_question = $this->prepareNextExamQuestion(2, $exam_taker);
}
} else {
switch ($level) {
case 5 :
if($array_answers['5']['fail'] == 2){ // if 2 fail level 5, set score to 16
$exam_taker->setScore(16);
$exam_taker->setCompleted(new \DateTime());
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$next_question = $this->prepareNextExamQuestion(4, $exam_taker);
}
break;
case 4 :
if($array_answers['4']['fail'] == 3){ // if 3 fail level 4, set score to 14
$exam_taker->setScore(14);
$exam_taker->setCompleted(new \DateTime());
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$next_question = $this->prepareNextExamQuestion(3, $exam_taker);
}
break;
case 3 :
if($array_answers['3']['fail'] == 3){ // if 3 fail level 3, set score to 12
$exam_taker->setScore(12);
$exam_taker->setCompleted(new \DateTime());
$this->createNewExamCertificationTaker($exam_taker, $user, $module_group);
} else {
$next_question = $this->prepareNextExamQuestion(2, $exam_taker);
}
break;
case 2 :
if($array_answers['2']['fail'] == 4){ // if 4 fail level 2, stop exam
$exam_taker->setScore(0);
$exam_taker->setCompleted(new \DateTime());
} else {
$next_question = $this->prepareNextExamQuestion(1, $exam_taker);
}
break;
case 1 :
if($array_answers['1']['fail'] == 5){ // if 5 fail level 1, stop exam
$exam_taker->setScore(0);
$exam_taker->setCompleted(new \DateTime());
} else {
$next_question = $this->prepareNextExamQuestion(1, $exam_taker);
}
break;
}
}
}
$em->flush();
// return next question to continue the current exam
return new JsonResponse();
}
/**
* Add next question to current exam taker
*/
public function prepareNextExamQuestion($level, $exam_taker){
// get manager
$em = $this->getDoctrine()->getManager();
// prepare test questions random array
// without questions already used
if(count($exam_taker->getQuestions()) > 0){
$questions_by_level = $em->getRepository('UserBundle:ExamQuestion')->getUnusedQuestionByLevel($level, $exam_taker->getModuleGroup(), $exam_taker->getQuestions());
} else {
$questions_by_level = $em->getRepository('UserBundle:ExamQuestion')->getUnusedQuestionByLevel1($level, $exam_taker->getModuleGroup());
}
// set a random question to display (the result is an array)
$random_question_id = array_rand($questions_by_level, 1);
$random_question = $questions_by_level[$random_question_id];
// add question to exam taker
$exam_taker->addQuestion($random_question);
$random_question->addExam($exam_taker);
// create exam answer taker
$exam_answer_taker = new ExamAnswerTaker();
$exam_answer_taker->setExam($exam_taker);
$exam_answer_taker->setQuestion($random_question);
$exam_taker->addAnswer($exam_answer_taker);
$em->persist($exam_answer_taker);
$em->flush();
return $random_question;
}
/**
* create or update a new exam certification taker
*/
public function createNewExamCertificationTaker($exam_taker, $user, $module_group){
// get manager
$em = $this->getDoctrine()->getManager();
// check if exam certification taker already exists
$exam_certif_taker = $em->getRepository('UserBundle:ExamCertificationTaker')->findOneBy(array('user' => $user, 'module_group' => $module_group));
if($exam_certif_taker){
$exam_certif_taker->setCompleted(new \DateTime());
$exam_certif_taker->getTries() == null ? $exam_certif_taker->setTries(1) : $exam_certif_taker->setTries(2);
} else {
$exam_certif_taker = new ExamCertificationTaker();
$exam_certif_taker->setExamTaker($exam_taker);
$exam_certif_taker->setUser($user);
$exam_certif_taker->setModuleGroup($module_group);
$exam_certif_taker->setCompleted(new \DateTime());
$exam_certif_taker->setTries(1);
$em->persist($exam_certif_taker);
}
}
/**
* Create a new Exam Taker
*/
public function createNewExamTaker($user, $module_group){
// get manager
$em = $this->getDoctrine()->getManager();
$exam_taker = new ExamTaker();
$exam_taker->setUser($user);
$exam_taker->setModuleGroup($module_group);
$em->persist($exam_taker);
$em->flush();
return $exam_taker;
}}
Линии в представлении с повторным вводом:
<form method="post" action="{{ path('user_exam_index', {'id': exam.moduleGroup.id}) }}">
<input type="submit" name="retry" class="waves-btn primary margin-top" value="Recommencer le quiz">
</form>
функция js:
function initAjaxSaveExamAnswer(exam_taker_id, question_id) {
$('body').on('click', '.initAjaxSaveExamAnswer', function(e){
e.preventDefault();
// check if an answer is checked
if (!$('input:radio[name="question"]:checked').val()) {
e.preventDefault();
alert("Tu dois choisir au moins une réponse !");
return;
}
var answer_id = $('input:radio[name="question"]:checked').val();
$.ajax({
type: "POST",
url: Routing.generate('user_exam_save'),
data: {exam_taker_id: exam_taker_id, question_id: question_id, answer_id: answer_id},
dataType: "json"
})
.done(function (data) {
location.reload();
})
.fail(function (jqXHR, textStatus, errorThrown) {
alert('Une erreur s\'est produite. Veuillez réessayer votre action...');
});
});
}
РЕДАКТИРОВАТЬ:
Вот процесс: я показываю первый вопрос с ответами переключателя. Затем я нажимаю на кнопку, которая запускает функцию AJAX. Функция Ajax проверяет правильность ответа или нет, а затем вычисляет следующий вопрос, чтобы отобразить или завершить тест, если, например, слишком много неправильных ответов. В обоих случаях функция ajax возвращает location.reload();
. Страница перезагружается благодаря indexAction () в контроллере. Когда тест завершен, отображается представление результатов, содержащее форму с кнопкой повторной отправки. Я нажимаю кнопку «Отправить повтор», чтобы перезапустить новый тест. Затем вызывается indexAction () и возвращает новый первый вопрос о новой викторине. В тот же момент я удаляю параметр повтора. Но я вижу, что содержимое запроса все еще содержит некоторую информацию о параметре retry. Может быть, это ключ? Хорошо параметр повтора удаляется в это время. Но когда я проверяю первый ответ, появляется следующий вопрос, и параметр retry возвращается в запрос, что является ошибкой, поскольку представление результатов никогда не может отображаться снова из-за этого плохого поведения.