使用现有和未存在的实体创建表单/调查(Symfony 3)

时间:2017-03-13 17:32:14

标签: php mysql forms symfony survey

我正在尝试在Symfony 3.2.4和PHP 5.6.28中为我的应用程序创建动态的Survey / Form Bundle

我有3个实体:调查/问题/答案

第一步是为每个用户创建一个调查。 问题必须在前面显示,并附有相关的答案字段。 提交时,它们将存储在DB,classic中。

问题已存储在DB Question.table。

我想让表单正常工作。显示存储在数据库中的所有问题并提交答案(与问题相关)。此外,所有答案都必须与调查相关联,因此我可以显示特定的调查结果(在用户完成调查后)

你能帮我把它搞定吗? 我只能为最后一个问题显示一个答案,我在控制器逻辑或我的FormType中做错了什么?

Answer.entity

    <?php

namespace SurveyBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Answer
 *
 * @ORM\Table(name="answer")
 * @ORM\Entity(repositoryClass="SurveyBundle\Repository\AnswerRepository")
 */
class Answer
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="text", type="string", length=255)
     */
    private $text;

    /**
     * Id from Company Entity
     *
     * @var int
     *
     * @ORM\ManyToOne(targetEntity="SurveyBundle\Entity\Survey", inversedBy="answer", cascade={"persist"})
     *
     */
    private $survey;

    /**
     * Id from Question Entity
     *
     * @ORM\OneToOne(targetEntity="SurveyBundle\Entity\Question", mappedBy="answer")
     */
    private $question;


    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set text
     *
     * @param string $text
     *
     * @return Answer
     */
    public function setText($text)
    {
        $this->text = $text;

        return $this;
    }

    /**
     * Get text
     *
     * @return string
     */
    public function getText()
    {
        return $this->text;
    }

    /**
     * @return int
     */
    public function getSurvey()
    {
        return $this->survey;
    }

    /**
     * @param int $survey
     */
    public function setSurvey($survey)
    {
        $this->survey = $survey;
    }

    /**
     * @return mixed
     */
    public function getQuestion()
    {
        return $this->question;
    }

    /**
     * @param mixed $question
     */
    public function setQuestion($question)
    {
        $this->question = $question;
    }

}

Question.entity

<?php

namespace SurveyBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Question
 *
 * @ORM\Table(name="question")
 * @ORM\Entity(repositoryClass="SurveyBundle\Repository\QuestionRepository")
 */
class Question
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="text", type="string", length=255)
     */
    private $text;


    public function __toString()
    {
        return (string) $this->text;
    }

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set text
     *
     * @param string $text
     *
     * @return Question
     */
    public function setText($text)
    {
        $this->text = $text;

        return $this;
    }

    /**
     * Get text
     *
     * @return string
     */
    public function getText()
    {
        return $this->text;
    }



}

Survey.entity

<?php

namespace SurveyBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Survey
 *
 * @ORM\Table(name="survey")
 * @ORM\Entity(repositoryClass="SurveyBundle\Repository\SurveyRepository")
 */
class Survey
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Id from Question Entity
     *
     * @ORM\OneToMany(targetEntity="SurveyBundle\Entity\Question", mappedBy="survey")
     */
    private $question;


    function __construct()
    {
        $this->question = new ArrayCollection();
    }

    public function getQuestion()
    {
        return $this->question;
    }

    /**
     * Id from Answer Entity
     *
     * @ORM\OneToMany(targetEntity="SurveyBundle\Entity\Answer", mappedBy="survey")
     */
    private $answer;

    public function setAnswer($answer)
    {
        $this->answer = $answer;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getAnswer()
    {
        return $this->answer;
    }

    /**
     * @param Question $question
     */
    public function addQuestion(Question $question)
    {
        $this->question[] = $question;
    }




}

Survey.controller

<?php

namespace SurveyBundle\Controller;

use SurveyBundle\Entity\Survey;
use SurveyBundle\Form\SurveyType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    /**
     * @Route("/survey", name="survey")
     */
    public function indexAction(Request $request)
    {

        $em = $this->getDoctrine()->getEntityManager();
        $questions = $em->getRepository('SurveyBundle:Question')->findAll();

        $survey = new Survey();

        //$ListProduits->setProduits($produits);

        foreach ($questions as $question)
            $survey->addQuestion($question);

        $form = $this->createForm(SurveyType::class, $survey);

        $form->handleRequest($request);

        if ($request->getMethod() === 'POST') {
            if ($form->isSubmitted() && $form->isValid()) {

                $em->persist($survey);
                $em->flush();

                $data = $form->getData();

                var_dump($data);

                echo 'OK2';

            }else {
                //ERROR
                trigger_error('Error - Survey hasn\'t been completed - Contact a Wizard');
            }
        }


        return $this->render('SurveyBundle:Default:index.html.twig',  array('form' => $form->createView()));
    }
}

Survey.FormType

<?php

namespace SurveyBundle\Form;

use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SurveyType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            //->add('name','text')
            ->add('question', EntityType::class,
                    'class' => 'SurveyBundle:Question',
                    'mapped' => false,
                    "multiple" => true,
                    'query_builder' => function (EntityRepository $er) {
                        return $er->createQueryBuilder('q')
                            ->orderBy('q.text', 'ASC');
                    },
            ))
            ->add(
                'answer',
                AnswerType::class
            )
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'SurveyBundle\Entity\Survey'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'referencebundle_survey';
    }


}

formView: front.survey

我只有一个答案字段,仅针对问题2.每个问题都需要一个。

此外,当我尝试提交时,我收到了此错误:

  

捕获致命错误:参数1传递给   Doctrine \ Common \ Collections \ ArrayCollection :: __ construct()必须是   类型数组,给定对象,调用   第605行的... / vendor / doctrine / orm / lib / Doctrine / ORM / UnitOfWork.php   和定义

2 个答案:

答案 0 :(得分:1)

您使用multiple =&gt; true语句呈现所有问题,但这并未将答案与每个问题相关联。那么你的表单会给出一个答案,所以你只能看到一个答案。

我认为您需要的是表单集合,请参阅文档:http://symfony.com/doc/current/form/form_collections.html

首先为每个问题/答案组合构建一个表单,然后从Survey.FormType中呈现表单集合。

答案 1 :(得分:1)

好的,我找到了一个解决方案,感谢@ehymel

在我的调查表单构建器中,我现在有2个CollectionType :问题&amp;回答 每个人都有自己的FormType。

我在我的控制器中做了一个关联Q&amp; A用我的调查对象,另一个用于在提交后保留我的答案。

我还改变了我的实体关系。

控制器:

$questions = $em->getRepository('SurveyBundle:Question')->findAll();

    $survey = new Survey();

    foreach ($questions as $question) {
        $answer = new Answer();
        $survey->getQuestion()->add($question);
        $answer->setQuestion($question);
        $survey->getAnswer()->add($answer);
    }

    $form = $this->createForm(SurveyType::class, $survey);

    $form->handleRequest($request);

    if ($request->getMethod() === 'POST') {
        if ($form->isSubmitted() && $form->isValid()) {
            $survey->setExperience($experience);
            $em->persist($survey);
            $em->flush();

            foreach ($survey->getAnswer() as $answer) {
                $answer->setSurvey($survey);
                $em->persist($answer);
                $em->flush();
            }
        } else {
            //ERROR
            trigger_error('Error - Experience hasn\'t been completed - Contact a Wizard');
        }
    }

SurveyType:

class SurveyType extends AbstractType{

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */

private $name = 'default_name';

public function getName(){
    return $this->name;
}

public function setName($name){
    $this->name = $name;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add(
            'question',
            CollectionType::class,
            array(
                'entry_type' => QuestionType::class)
        )
        ->add(
            'answer',
            CollectionType::class,
            array(
            'entry_type' => AnswerType::class)
        );
}

/**
 * {@inheritdoc}
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'SurveyBundle\Entity\Survey'
    ));
}

/**
 * {@inheritdoc}
 */
public function getBlockPrefix()
{
    return 'referencebundle_survey';
}

}