简体   繁体   English

将所有记录插入Symfony中的联结表中

[英]Insert all records into junction table in Symfony

I have a next tables: quiz, question, and question_quiz. 我有下一张表:测验,问题和question_quiz。 I have a many-to-many relationship. 我有一对多的关系。 Insertion work right for table quiz and question, but in table question_quiz inserted only single record. 插入工作适用于表测验和问题,但是在表question_quiz中仅插入单个记录。

My tables 我的桌子

"question", it's all right. “问题”,没关系。

+----+--------+
| id | title  |
+----+--------+
| 61 | Title1 |
| 62 | Title2 |
| 63 | Title3 |
+----+--------+

"quiz", it's all right. “测验”,没关系。

+----+-------+--------+
| id | name  | status |
+----+-------+--------+
| 27 | Name1 |      0 |
+----+-------+--------+

"question_quiz" “question_quiz”

+-------------+---------+
| question_id | quiz_id |
+-------------+---------+
|          61 |      27 |
+-------------+---------+

In last table must be inserted 61,62,63 quiestion_id, but inserted only single record. 在最后一个表中必须插入61,62,63 quiestion_id,但只能插入单个记录。

Fragment of my controller. 我的控制器的片段。

   $quiz = new Quiz();
   $question = new Question();
   $form = $this->get('form.factory')->createNamed('quiz', QuizType::class, $quiz);
   $quiz->getQuestions()->add($question);
   $question->addQuiz($quiz);
   $form->handleRequest($request);
   if ($form->isSubmitted() && $form->isValid()) {
      $em = $this->getDoctrine()->getManager();
      $em->persist($quiz);
      $em->persist($question);
      $em->flush();
}

The call evidence of a question entity. 问题实体的通话证据。

  $quiz->getQuestions()->add($question);
  $question->addQuiz($quiz);

I use the collection type, and I can insert any number of questions. 我使用集合类型,我可以插入任何数量的问题。

UPDATE QuizType form. UPDATE QuizType表单。

class QuizType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class, array('attr' => ['class' => 'form-control name-quiz'], 'label' => 'Name Quiz'))
            ->add('status', CheckboxType::class, array(
                'label'    => 'Status Quiz',
                'required' => false))
            ->add('save', SubmitType::class, ['label' => 'Add', 'attr' => ['class' => 'btn btn-primary']]);
        $builder
            ->add('questions', CollectionType::class, array(
                'entry_type' => QuestionType::class,
                'entry_options' => array('label' => false),
                'allow_add' => true,
            ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Quiz::class
        ]);
    }
}

if I debug the method addQuestion() I got error INSERT INTO question (title) VALUES (?)' with params [null]. 如果我调试方法addQuestion()出现带有参数[null]的错误INSERT INTO问题(标题)VALUES(?)'。 But if I dubug method addQuiz I get 但是如果我使用dubug方法addQuiz我会得到

   Question {#583 ▼
  -id: null
  -title: "123"
  -quiz: ArrayCollection {#584 ▼
    -elements: array:1 [▼
      0 => Quiz {#581 ▼
        -id: null
        -name: "123"
        -questions: ArrayCollection {#580 ▶}
        -status: false
      }
    ]
  }
  -answers: ArrayCollection {#585 ▶}
}

The debug $form->get('questions')->getData() return 调试$ form-> get('questions')-> getData()返回

ArrayCollection {#733 ▼
  -elements: array:2 [▼
    0 => Question {#736 ▶}
    1 => Question {#981 ▶}
  ]
}

Without Quiz and Question entities - it is hard to tell. 没有QuizQuestion实体-很难分辨。 BUT

I think the problem is in your controller. 我认为问题出在您的控制器上。

 $quiz = new Quiz();
 $question = new Question();
 //...
 $question->addQuiz($quiz);

So you create a new Quiz, which should have multiple questions, right? 因此,您创建了一个新的测验,应该有多个问题,对吗? But you asign a question only once.. 但是您只提出一个问题。

$question->addQuiz($quiz);

so the right way would be like (a bit verbose so you can get the point) 所以正确的方法就像(有点冗长,以便您能理解要点)

$quiz = new Quiz();
//Q 1
$question_1 = new Question('Title1'); 
$quiz->addQuestion( $question_1 ); 
//Q 2
$question_2 = new Question('Title2'); 
$quiz->addQuestion( $question_2 );
//Q 3
$question_2 = new Question('Title3'); 
$quiz->addQuestion( $question_3 );

$em->persist($question_1);
$em->persist($question_2);
$em->persist($question_2);
$em->persist($quiz);
$em->flush();

Take a look at this example ( https://gist.github.com/Ocramius/3121916 ) for ManyToMany relation and especial to addUSerGroup() and addUser() methods. 看一下此示例( https://gist.github.com/Ocramius/3121916 ),了解ManyToMany关系以及对addUSerGroup()addUser()方法的addUser()

Try the suggested method in a controller (without form) and see if it works and if you get more than one rows into question_quiz table 在控制器(无格式)中尝试建议的方法,看看它是否有效,以及是否在question_quiz表中包含多行

UPDATE: 更新:

I think the "magic" you're looking for is cascade={"persist"} in your Quiz Entity. 我认为您要寻找的“魔术”是您的测验实体中的cascade={"persist"} Take a look at this article ( https://knpuniversity.com/screencast/collections/add-new-collection-cascade-persist ). 看一下这篇文章( https://knpuniversity.com/screencast/collections/add-new-collection-cascade-persist )。 Even though the video isn't free, the text is fine. 即使视频不是免费的,文本也很好。

1)set up cascade in yout entity 1)在您的实体中设置cascade

2)updated you addQuestion() method in Quiz class like following 2)更新您在Quiz类中的addQuestion()方法,如下所示

public function addQuestion(Question $question)
{
  // do not add same questions more than once. 
  if ($this->questions->contains($question)) {
    return;
  }
  $this->questions[] = $question; // to add new question to that quiz
  $question->addQuiz($this); // this quiz now also belongs to a question
}

3) get embed collection to work with prototype => http://symfony.com/doc/current/form/form_collections.html . 3)获取嵌入集合以使用prototype => http://symfony.com/doc/current/form/form_collections.html So you can add new Questions on the fly 因此您可以即时添加新问题

4)After submit, just call: 4)提交后,只需致电:

if ($form->isSubmitted() && $form->isValid()) {
   $quiz = $form->getData();
   $em->persist($quiz);
   $em->flush();
}

4.1)If that doesn't work, try looping over the submitted collection of questions 4.1)如果这样不起作用,请尝试遍历提交的问题集合

if ($form->isSubmitted() && $form->isValid()) {
   $quiz = $form->getData();
   // since getQuestions() gives you an ArrayCollection, isEmpty is a built in method
   if(!$quiz->getQuestions()->isEmpty())
   {
     // this is kinda bad, but you'll have to debug and play around
     foreach ($quiz->getQuestions() as $new_question)
     {
       $em->persist($new_question);
     }
   }
   $em->persist($quiz);
   $em->flush();
}

I resolved my problem. 我解决了我的问题。 I post my code maybe it will help somebody. 我发布我的代码,也许会对某人有所帮助。

My entity Question 我的实体Question

class Question
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

/**
 * @ORM\Column(type="text")
 */
private $title;

/**
 * @ORM\ManyToMany(targetEntity="App\Entity\Quiz", inversedBy="questions")
 */
private $quiz;


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

public function getId(): ?int
{
    return $this->id;
}

public function getTitle(): ?string
{
    return $this->title;
}

public function setTitle(string $title): self
{
    $this->title = $title;

    return $this;
}


/**
 * @return Collection|Quiz[]
 */
public function getQuiz(): Collection
{
    return $this->quiz;
}

public function addQuiz(Quiz $quiz): self
{
    if (!$this->quiz->contains($quiz)) {
        $this->quiz[] = $quiz;
    }

    return $this;
}

public function removeQuiz(Quiz $quiz): self
{
    if ($this->quiz->contains($quiz)) {
        $this->quiz->removeElement($quiz);
    }

    return $this;
    }
}

My Entity Quiz 我的实体Quiz

class Quiz
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
/**
 * @ORM\Column(type="string", length=191)
 */
private $name;
/**
 * @ORM\ManyToMany(targetEntity="App\Entity\Question", mappedBy="quiz", cascade={"persist"})
 */
private $questions;

/**
 * @ORM\Column(type="boolean")
 */
private $status;

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

public function getId(): ?int
{
    return $this->id;
}

/**
 * @return string|null
 */
public function getName(): ?string
{
    return $this->name;
}

public function setName(string $name): self
{
    $this->name = $name;

    return $this;
}

/**
 * @return Collection|Question[]
 */
public function getQuestions(): Collection
{
    return $this->questions;
}

public function addQuestion(Question $question): self
{
    if (!$this->questions->contains($question)) {
        $this->questions[] = $question;
        $question->addQuiz($this);
    }

    return $this;
}

public function removeQuestion(Question $question): self
{
    if ($this->questions->contains($question)) {
        $this->questions->removeElement($question);
        $question->removeQuiz($this);
    }

    return $this;
}

public function getStatus(): ?bool
{
    return $this->status;
}

public function setStatus(bool $status): self
{
    $this->status = $status;

    return $this;
   }
}

QuestionType form QuestionType表格

 public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title', TextareaType::class, array('attr' => array('class' => 'form-control'), 'label' => false));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Question::class
        ]);
    }

QuizType form QuizType表单

   public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class, array('attr' => ['class' => 'form-control name-quiz'], 'label' => 'Name quiz'))
            ->add('status', CheckboxType::class, array(
                'label'    => 'Status quiz',
                'required' => false))
            ->add('save', SubmitType::class, ['label' => 'Add', 'attr' => ['class' => 'btn btn-primary']]);
        $builder
            ->add('questions', CollectionType::class, array(
                'entry_type' => QuestionType::class,
                'entry_options' => array('label' => false),
                'allow_add' => true,
                'by_reference' => false,
            ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Quiz::class
        ]);
    }

And finally my controller 最后是我的控制器

    $quiz = new Quiz();
    $form = $this->get('form.factory')->createNamed('quiz', QuizType::class, $quiz);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($quiz);
        $em->flush();
        return $this->redirectToRoute('admin');

    }

It's works, yea :) Thanks all. 是的,是的:)谢谢大家。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM