1

由于 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;
        }
    }
}

最后两个是辅助方法,因此我可以添加/检索个人分数。类型检查卷积是由于我在这里遇到的错误

分数:

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));
}

我的表格类型....

调查类型:

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';
    }
}

调查清单项目类型:

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';
    }
}

调查评分类型:

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/lib/Doctrine 中调用/ORM/UnitOfWork.php 在第 547 行并在 /home/kevin/www/project/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php 第 47 行定义

认为这与问题的相关分数有关,因为它们应该是 Question 中的一个数组(集合),但在这种情况下它们是个别实例。唯一的问题是我不确定如何解决它。

我在想我的表单设置可能太复杂了。我真正需要做的就是将每个 Question.id 附加到每个相关的分数。我只是不确定构建它的表单部分的最佳方法,以便一切都正确持久。

4

3 回答 3

1

我相信你的错误在这里

    $rating = new Score();
    //...
    $question->setRatings($rating);

通常,如果您的 Entity 中有一个 ArrayCollection,那么您就有 addChildEntity 和 removeChildEntity 方法,它们可以在 ArrayCollection 中添加和删除元素。

setRatings()将采用一组实体,而不是单个实体。

假设您确实有此方法,请尝试

$question->addRating($rating);
于 2013-06-11T22:15:54.430 回答
0

我能够通过简单地处理分数来解决它。因此,通过这种方法,我能够删除SurveyListItemType,并进行以下更改:

调查类型:

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。

调查评级类型:

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));
}

由于三种表单类型,我感觉我做错了。这真的是一种糟糕的代码气味。感谢大家的耐心和帮助。:)

于 2013-06-12T01:19:07.460 回答
0

我认为您的 setRating 方法有误。

你有

 $this->score->add($score);

它应该是:

  $this->scores->add($score);
于 2013-06-11T21:14:31.650 回答