2013-06-11 1 views
1

Les noms ont été modifiés en raison de NDA. J'essaie de trouver un formulaire d'enquête. Chaque question d'enquête peut avoir plusieurs réponses/scores, donc il y a une relation naturelle 1: * avec eux. Cela dit, pour le formulaire destiné au public, je dois avoir une relation 1: 1 entre le score et la question à laquelle il se rapporte, et c'est ce sur quoi je travaille actuellement. À l'heure actuelle, l'enquête est ouverte au public, de sorte que chaque enquête terminée est pas liée à un utilisateur.Symfony2 et Doctrine - 'Erreur fatale détectable' lors du vidage

Les parties intéressantes de ma configuration actuelle sont les suivants ...

Question:

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

Ces deux dernières sont des méthodes helper je peux donc ajouter/récupérer les scores individuels. Le type de contrôle étaient convolutions en raison d'une erreur que je rencontrais here

Score:

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 
} 

méthode Contrôleur:

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

Mes types de formulaires ....

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

D'accord, avec tout cela, j'obtiens l'erreur suivante lors EntityManager de Doctrine tente de débusquer() dans mon action de contrôleur:

Catchable Fatal Error: Argument 1 passed to Doctrine\Common\Collections\ArrayCollection::__construct() must be of the type array, object given, called in /home/kevin/www/project/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 547 and defined in /home/kevin/www/project/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php line 47

I crois il a à voir avec les scores liés aux questions, car ils sont censés être un tableau (collection) dans Question, mais ce sont des instances individuelles dans ce cas. Le seul problème est que je ne suis pas sûr de savoir comment le réparer. Je pense que la configuration de ma forme peut être trop complexe. Tout ce que j'ai vraiment besoin de faire est d'attacher chaque Question.id à chaque Score associé. Je ne suis pas sûr de la meilleure façon de construire la partie forme de sorte que tout est correctement conservé.

Répondre

0

j'ai pu le résoudre en manipulant simplement les scores. Ainsi, avec cette approche, j'ai pu enlever SurveyListItemType, et effectuez les modifications suivantes:

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

Notez comment le type de collection est maintenant mis en correspondance avec 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'; 
    } 
} 

Et mon action de contrôleur modifié:

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

J'ai eu un sentiment que je faisais mal en raison des trois types de formulaires. Cela a vraiment sauté comme une mauvaise odeur de code. Merci à tous pour leur patience et leurs efforts pour aider. :)

0

Je pense que vous avez une erreur dans votre méthode setRating.

Vous avez

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

Il devrait être:

$this->scores->add($score); 
+0

Non, c'est juste une faute de frappe de ma part pas brisé mon NDA ici. Dans le vrai code, c'est correct. –

1

Je crois que votre erreur est ici

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

Habituellement, si vous avez un ArrayCollection dans votre entité, vous avez Méthodes addChildEntity et removeChildEntity qui ajoutent et suppriment des éléments de ArrayCollection.

setRatings() prendrait un tableau d'entités plutôt qu'une seule entité.

En supposant que vous avez cette méthode, essayez

$question->addRating($rating); 
+0

Ne serait-ce pas ce que j'ai ajouté comme méthodes d'aide à la question? Ou est-il automatiquement ajouté via Doctrine, donc je n'ai pas besoin de l'ajouter manuellement à mes propres entités? –

Questions connexes