Symfony2和Doctrine - 关于同花顺的“可捕获的致命错误”

时间:2013-06-11 20:10:11

标签: symfony doctrine-orm

由于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附加到每个相关的分数。我只是不确定构建它的表单部分的最佳方法,所以一切都保持正确。

3 个答案:

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

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