创建测验表单symfony

Ces*_*sar 1 php symfony

我正在尝试对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并将其发送给视图,对吗?

lor*_*dos 5

我知道这不是这样做的方法,我应该创建一个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)