由于NDA,名称发生了变化。
我正在努力想出一份调查表。每个调查问题都可以有多个答案/分数,因此与他们之间存在自然的1:*关系。也就是说,对于面向公众的形式,我需要在得分和与之相关的问题之间建立1:1的关系,这就是我现在所做的工作。目前,调查对公众开放,因此每个完成的调查都与用户相关的 。
我当前设置的有趣部分如下......
问题:
namespace Acme\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class Question
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string question
*
* @ORM\Column(name="question", type="string", length=255)
*/
private $question;
/**
* @var ArrayCollection scores
*
* @ORM\OneToMany(targetEntity="Score", mappedBy="question")
*/
private $scores;
public function __construct()
{
$this->scores = new ArrayCollection();
}
// other getters and setters
/**
* @param $score
*/
public function setScore($score)
{
$this->scores->add($score);
}
/**
* @return mixed
*/
public function getScore()
{
if (get_class($this->scores) === 'ArrayCollection') {
return $this->scores->current();
} else {
return $this->scores;
}
}
}
最后两个是辅助方法,所以我可以添加/检索单个分数。类型检查卷积是由于我遇到的错误here
分:
namespace Acme\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class Score
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var integer $question
*
* @ORM\ManyToOne(targetEntity="Question", inversedBy="scores")
* @ORM\JoinColumn(name="question_id", referencedColumnName="id")
*/
private $question;
/**
* @var float score
*
* @ORM\Column(name="score", type="float")
*/
private $score;
// getters and setters
}
控制器方法:
public function takeSurveyAction(Request $request)
{
$em = $this->get('doctrine')->getManager();
$questions = $em->getRepository('Acme\MyBundle\Entity\Question')->findAll();
$viewQuestions = array();
foreach ($questions as $question) {
$viewQuestions[] = $question;
$rating = new Score();
$rating->setQuestion($question->getId());
$question->setRatings($rating);
}
$form = $this->createForm(new SurveyType(), array('questions' => $questions));
if ('POST' === $request->getMethod()) {
$form->bind($request);
if ($form->isValid()) {
foreach ($questions as $q) {
$em->persist($q);
}
$em->flush();
$em->clear();
$url = $this->get('router')->generate('_main');
$response = new RedirectResponse($url);
return $response;
}
}
return $this->render('MyBundle:Survey:take.html.twig', array('form' => $form->createView(), 'questions' => $viewQuestions));
}
我的表单类型......
SurveyType:
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SurveyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('questions', 'collection', array('type' => new SurveyListItemType()));
}
public function getName()
{
return 'survey';
}
}
SurveyListItemType:
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SurveyListItemType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('rating', new SurveyScoreType());
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Acme\MyBundle\Entity\Question'));
}
public function getName()
{
return 'survey_list_item_type';
}
}
SurveyScoreType:
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SurveyRatingType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('score', 'choice', array('choices' => array(
'0' => '',
'0.5' => '',
'1' => '',
'1.5' => '',
'2' => '',
'2.5' => '',
'3' => '',
'3.5' => '',
'4' => '',
'4.5' => '',
'5' => ''
), 'expanded' => true, 'multiple' => false));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Acme\MyBundle\Entity\Score'));
}
public function getName()
{
return 'survey_score_type';
}
}
好的,所有这些,当Doctrine的EntityManager尝试在我的控制器操作中刷新()时,我收到以下错误:
捕获致命错误:传递给Doctrine \ Common \ Collections \ ArrayCollection :: __ construct()的参数1必须是类型数组,给定对象,在/ home / kevin / www / project / vendor / doctrine / orm /中调用第547行的lib / Doctrine / ORM / UnitOfWork.php,在/home/kevin/www/project/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php第47行中定义
我相信它与问题的相关分数有关,因为它们应该是问题中的数组(集合),但在这种情况下它们是个别实例。唯一的问题是我不确定如何解决它。
我认为我的表单设置可能过于复杂。我真正需要做的就是将每个Question.id附加到每个相关的分数。我只是不确定构建它的表单部分的最佳方法,所以一切都保持正确。
答案 0 :(得分:1)
我相信你的错误就在这里
$rating = new Score();
//...
$question->setRatings($rating);
通常,如果你的Entity中有一个ArrayCollection,那么你有addChildEntity和removeChildEntity方法来添加和删除ArrayCollection中的元素。
setRatings()
将采用一系列实体,而不是单个实体。
假设您有这种方法,请尝试
$question->addRating($rating);
答案 1 :(得分:0)
我认为你的setRating方法有误。
你有
$this->score->add($score);
应该是:
$this->scores->add($score);
答案 2 :(得分:0)
我能够通过简单地处理分数来解决它。因此,通过这种方法,我可以删除SurveyListItemType
,并进行以下更改:
SurveyType:
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SurveyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('scores', 'collection', array('type' => new SurveyRatingType()));
}
public function getName()
{
return 'survey';
}
}
注意集合类型现在如何映射到SurveyRatingType。
SurveyRatingType:
namespace Acme\MyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class SurveyRatingType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('score', 'choice', array('choices' => array(
'0' => '',
'0.5' => '',
'1' => '',
'1.5' => '',
'2' => '',
'2.5' => '',
'3' => '',
'3.5' => '',
'4' => '',
'4.5' => '',
'5' => ''
), 'expanded' => true, 'multiple' => false));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Acme\MyBundle\Entity\Score'));
}
public function getName()
{
return 'survey_rating_type';
}
}
我修改过的控制器动作:
public function takeSurveyAction(Request $request)
{
$em = $this->get('doctrine')->getManager();
$questions = $em->getRepository('Acme\MyBundle\Entity\Question')->findAll();
$ratings = array();
foreach ($questions as $question) {
$rating = new SurveyRating();
$rating->setQuestion($question);
$ratings[] = $rating;
}
$form = $this->createForm(new SurveyType(), array('ratings' => $ratings));
if ('POST' === $request->getMethod()) {
$form->bind($request);
if ($form->isValid()) {
foreach ($ratings as $r) {
$em->persist($r);
}
$em->flush();
$em->clear();
$url = $this->get('router')->generate('_main');
$response = new RedirectResponse($url);
return $response;
}
}
return $this->render('MyBundle:Survey:take.html.twig', array('form' => $form->createView(), 'questions' => $questions));
}
我有一种感觉,由于三种表格类型,我做错了。这真是一个糟糕的代码味道。感谢大家的耐心和帮助。 :)