我知道这不是这样做的,我应该创建一个窗体并将其发送到视图的权利?
这很大程度上取决于您的观点。 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
为Quiz
,显示问题文本并遍历answers
为每个Question
,这几乎是相同的,你在做什么。但是,如果我要再次构建这样的东西,我会尝试遵循最佳实践并为其定义表单类。我将使用实体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;
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;
下面的代码是一个未测试的示例,这只是给你一个想法如何构建您的表单类型
创建表单类型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';
}
}
为了使这项工作,你需要设置Question
创建时,它传递给表单中的数据对象上,这样的形式只会显示有关这个问题的答案。
E.g.在你的控制器:
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
));
在你的控制,你会比需要准备像数据:
/** @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);
$userQuizAnswer = new UserQuizAnswer();
$userQuizAnswer->setQuestion($question);
$this->createForm(new UserQuizAnswer(), $userQuizAnswer);
与UserQuizAnswerType
表单类型的集合创建一个表单类型UserQuizResultType
“我知道这不是正确的做法”。为什么?从你的角度来看它有什么问题?此外,没有任何代码可以帮助你解决问题。屏幕截图只能说明故事的一小部分内容。 – ADyson
你可以添加更多的信息,你的表单(类)和视图是怎样的? – lordrhodos
@lordrhodos我编辑了一下,你想要我添加一些关于我的表单的信息? – Cesar