我正在尝试对symfony进行测验,但是我很难进行渲染。
这是我的数据库:
一个序列(测验)可以有很多问题,这些问题有多个答案,用户可以选择一个答案。
但是,它的构建方式不知道如何创建一个简单的表单,因此当用户选择答案时,它将更新该用户。简单的树枝渲染:
这是视图代码(我已经删除了一些html):
{% for sequence in enquete.sequences %}
{% for questseq in sequence.QuestionsSequence %}
<input id="textinput" name="textinput" type="text" placeholder="{{questseq.Intitule}}" class="form-control input-md">
<!-- Multiple Checkboxes -->
<div class="form-group">
<label class="col-md-4 control-label" for="checkboxes">Réponses :</label>
{% for repseq in questseq.ReponsesQuestion %}
<div class="checkbox">
<label for="checkboxes-{{repseq.id}}">
<input type="checkbox" name="checkboxes" id="checkboxes-{{repseq.id}}" value="1">
{{ repseq.Intitule }}
{%endfor%}
{% endfor %}
{%endfor%}
Run Code Online (Sandbox Code Playgroud)
我知道这不是这样做的方法,我应该创建一个Form并将其发送给视图,对吗?
我知道这不是这样做的方法,我应该创建一个Form并将其发送给视图,对吗?
这在很大程度上取决于您的观点。Symfony最佳实践建议将您的表单定义为PHP类,但要在这种情况下实现该目标并非易事。
在过去的一个创建MOOC的项目中,我面临着类似的任务:在每个模块的末尾显示一个测验,其中只有一个答案类型(单选按钮)的多个问题。我已经实现了以下实体- 可以将其映射到您的实体:
Quiz (序列)Question (question_sequence)Answer (response_sequence)UserQuizAnswer (response_sequence_utilisateur)UserQuizResult User (实用程序)除了创建的持久实体外,我还创建了未映射的类,UserQuizAnswerEvaluation并且UserQuizEvaluation由于我需要检查天气,因此用户达到了正确答案的某个阈值(80%),才能通过测验。
当时我的解决方案(最快,不是最好)是将测验对象从控制器传递到树枝视图,并在没有任何Form Classs的情况下呈现表单:
# src/AppBundle/Controller/QuizController.php
public function showAction($id, Request $request)
{
$quiz = $this->get('app.quiz.manager')->findQuizById($id);
if (!$quiz) {
throw new EntityNotFoundException();
}
$viewParams = ['quiz' => $quiz];
...
return $this->render(
'AppBundle:quiz:show.html.twig',
$viewParams
);
}
Run Code Online (Sandbox Code Playgroud)
在视图中,我遍历questionsfor Quiz,显示问题文本,并遍历answersfor每个Question,所以您所做的几乎相同。
# src/AppBundle/Resources/views/quiz/show.html.twig
<form action="{{ path('quiz_evaluate', {'id': quiz.id}) }}" method="post">
{% for question in quiz.questions %}
<div class="content-element">
<p>{{ loop.index }}. {{ question.text }}</p>
{% for answer in question.answers %}
{% if evaluation is defined %}
{% if (answer.id == evaluation.answers[question.id].answerId) %}
{% set checked = 'checked' %}
{% else %}
{% set checked = '' %}
{% endif %}
{% endif %}
<div class="radio">
<label>
<input type="radio" name="answers[{{ question.id }}]" value="{{ answer.id }}"
{% if checked is defined %}{{ checked }}{% endif %} >
<span class="upper">{{ loop.index|numberToAlphabet }}.</span> {{ answer.text }}
</label>
</div>
{% endfor %}
</div>
{% if evaluation is defined %}
<br>
{% if evaluation.answers[question.id].isCorrect %}
<div class="alert alert-success">
<h3><i class="fa fa-check"> Success</i></h3>
{% else %}
<div class="alert alert-danger">
<h3><i class="fa fa-times"></i> Almost, please try again</h3>
{% endif %}
{{ question.answerDescription }}
</div>
{% endif %}
<div class="divider"></div>
{% endfor %}
{% if app.user and is_granted('ROLE_PRE_SURVEY_COMPLETED') %}
<input type="submit" class="btn btn-enroll btn-block" value="Submit your answers">
</form>
Run Code Online (Sandbox Code Playgroud)
但是,如果我要再次构建类似的东西,我将尝试遵循最佳实践并为其定义表单类。我将使用一个UserQuizAnswer或多个UserQuizResult实体作为表单类型的基础,并相应地构建表单。
这是两个实体的摘录,以查看映射定义:
UserQuizAnswer
# src/AppBundle/Entity/UserQuizAnswer.php
/**
* UserQuizAnswer
*
* @ORM\Table(name="user__quiz__answer")
* @ORM\Entity
*/
class UserQuizAnswer
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var Question
*
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Question")
*/
private $question;
/**
* @var Answer
*
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Answer")
*/
private $answer;
/**
* @var UserQuizResult
*
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\UserQuizResult", inversedBy="answers")
*/
private $quizResult;
Run Code Online (Sandbox Code Playgroud)
UserQuizResult
# src/AppBundle/Entity/UserQuizResult.php
/**
* UserQuizResult
*
* @ORM\Table(name="user__quiz__result")
* @ORM\Entity(repositoryClass="AppBundle\Entity\UserQuizResultRepository")
*/
class UserQuizResult
{
use ORMBehaviors\Timestampable\Timestampable;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var User
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="quizResults")
*/
private $user;
/**
* @var Quiz
*
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Quiz", inversedBy="results")
*/
private $quiz;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\UserQuizAnswer", mappedBy="quizResult", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private $answers;
Run Code Online (Sandbox Code Playgroud)
以下代码是未经测试的示例,它只是为了让您了解如何构建表单类型类
创建一个UserQuizAnswerType引用该问题的表单类型,并提供该问题的可能答案。
# src/AppBundle/Form/UserQuizAnswerType.php
<?php
namespace AppBundle\Form;
use AppBundle\Entity\Question;
use AppBundle\Entity\UserQuizAnswer;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserQuizAnswerType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
/** @var UserQuizAnswer $userQuizAnswer */
$userQuizAnswer = $builder->getData();
/** @var Question $question */
$question = $userQuizAnswer->getQuestion();
$builder
->add('question')
->add(
'answer',
EntityType::class,
[
'class' => 'AppBundle:Answer',
'query_builder' => function (EntityRepository $er) use (
$question
) {
return $er->createQueryBuilder('a')
->where('a.question = :question')
->setParameter('question', $question);
},
'choice_label' => 'text',
]
);
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
[
'data_class' => 'AppBundle\Entity\UserQuizAnswer',
]
);
}
/**
* @return string
*/
public function getName()
{
return 'appbundle_userquizanswer';
}
}
Run Code Online (Sandbox Code Playgroud)
为了完成这项工作,您需要Question在创建表单时在传递给表单的数据对象上设置,因此表单将仅显示与该问题相关的答案。
例如,在您的控制器中:
$userQuizAnswer = new UserQuizAnswer();
$userQuizAnswer->setQuestion($question);
$this->createForm(new UserQuizAnswer(), $userQuizAnswer);
Run Code Online (Sandbox Code Playgroud)
创建具有表单类型UserQuizResultType集合的UserQuizAnswerType表单类型:
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
// ...
$builder->add('answers', CollectionType::class, array(
'entry_type' => UserQuizAnswerType::class,
'allow_add' => false
));
Run Code Online (Sandbox Code Playgroud)
在您的控制器中,您将需要准备如下数据:
/** @var UserQuizResult $userQuizResult */
$userQuizResult = new UserQuizResult();
$userQuizResult->setUser($this->getUser());
/** @var Question $question */
foreach ($quiz->getQuestions() as $question) {
$userQuizAnswer = new UserQuizAnswer();
$userQuizAnswer->setQuestion($question);
// add answer to "collection"
$userQuizResult->addAnswer($userQuizAnswer);
}
$this->createForm(new UserQuizResult(), $userQuizResult);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1239 次 |
| 最近记录: |