我正试图在symfony中进行一项搜索,但我很难完成渲染。
这是我的数据库:
序列(quizz)可以有很多问题,这些问题有多个答案,用户可以选择一个答案。
但是它的构建方式,我不知道如何创建一个简单的表单,所以当用户选择一个答案时,它将更新该用户。 简单的树枝渲染:
这是视图代码(我删除了一些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%}
我知道这不是这样做的方法,我应该创建一个表格并将其发送到视图中吗?
答案 0 :(得分:2)
我知道这不是这样做的方法,我应该创建一个表格并将其发送到视图中吗?
这在很大程度上取决于你的观点。 Symfony Best Practices建议将表单定义为PHP类,但在这种情况下实现这一点并不容易。
在我过去创建MOOC的一个项目中,我面临着类似的任务:在每个模块的末尾显示一个测验,其中只有一个答案类型的多个问题(单选按钮)。我已经实现了以下实体 - 可以映射到您的实体:
Quiz
(序列)Question
(question_sequence)Answer
(response_sequence)UserQuizAnswer
(response_sequence_utilisateur)UserQuizResult
User
(utilisateur)除了我创建的持久性实体未映射类UserQuizAnswerEvaluation
和UserQuizEvaluation
,因为我需要检查天气,用户达到了某个阈值(80%)通过测验的正确答案。
我当时的解决方案(最快,不是最好的)是将测验对象从控制器传递到树枝视图,并在没有任何Form Classes的情况下渲染表单:
# 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
);
}
在视图中,我遍历questions
的{{1}},显示问题文本,并针对每个Quiz
迭代answers
,所以几乎相同你在干嘛。
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>
和UserQuizAnswer
实体作为表单类型的基础,并相应地构建表单。
以下是两个实体的摘录,以查看映射定义:
<强> UserQuizAnswer 强>
UserQuizResult
<强> UserQuizResult 强>
# 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;
以下代码是一个未经测试的示例,它只是为了让您了解如何构建表单类型类
创建表单类型# 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;
,引用该问题并呈现该问题的可能答案。
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';
}
}
,因此表单只会显示与该问题相关的答案。
E.g。在你的控制器中:
Question
使用$userQuizAnswer = new UserQuizAnswer();
$userQuizAnswer->setQuestion($question);
$this->createForm(new UserQuizAnswer(), $userQuizAnswer);
表单类型的集合创建表单类型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
));