在 Symfony 中将所有记录插入连接 table
Insert all records into junction table in Symfony
我有下一个 table:测验、问题和 question_quiz。我有一个多对多的关系。
table 测验和问题的插入工作正常,但在 table question_quiz 中仅插入一条记录。
我的table
"question",没问题
+----+--------+
| id | title |
+----+--------+
| 61 | Title1 |
| 62 | Title2 |
| 63 | Title3 |
+----+--------+
"quiz",没问题
+----+-------+--------+
| id | name | status |
+----+-------+--------+
| 27 | Name1 | 0 |
+----+-------+--------+
"question_quiz"
+-------------+---------+
| question_id | quiz_id |
+-------------+---------+
| 61 | 27 |
+-------------+---------+
最后table必须插入61,62,63quiestion_id,但只能插入单条记录。
我的控制器片段。
$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();
}
问题实体的调用证据
$quiz->getQuestions()->add($question);
$question->addQuiz($quiz);
我用的是集合类型,可以插入任意数量的问题
更新测验类型表格。
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
]);
}
}
如果我调试方法 addQuestion()
我收到错误 INSERT INTO question (title) VALUES (?)' with params [null]。但是如果我调试方法 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 ▶}
}
调试 $form->get('questions')->getData() return
ArrayCollection {#733 ▼
-elements: array:2 [▼
0 => Question {#736 ▶}
1 => Question {#981 ▶}
]
}
没有 Quiz
和 Question
实体 - 很难说。但是
我认为问题出在您的控制器上。
$quiz = new Quiz();
$question = new Question();
//...
$question->addQuiz($quiz);
所以你创建了一个新的测验,它应该有多个问题,对吧?
但是你只分配了一次问题..
$question->addQuiz($quiz);
所以正确的方法应该是(有点冗长,这样你就明白了)
$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();
查看此示例 (https://gist.github.com/Ocramius/3121916),了解 ManyToMany 关系,特别是 addUSerGroup()
和 addUser()
方法。
在控制器(无表格)中尝试建议的方法,看看它是否有效,如果你得到超过一行 question_quiz
table
更新:
我认为您正在寻找的 "magic" 在您的测验实体中是 cascade={"persist"}
。看看这篇文章 (https://knpuniversity.com/screencast/collections/add-new-collection-cascade-persist)。尽管视频不是免费的,但文字很好。
1) 在您的实体
中设置 cascade
2)更新了你 addQuestion()
测验 class 中的方法,如下所示
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) 获取嵌入集合以使用 prototype
=> http://symfony.com/doc/current/form/form_collections.html。这样您就可以随时添加新问题
4)提交后调用:
if ($form->isSubmitted() && $form->isValid()) {
$quiz = $form->getData();
$em->persist($quiz);
$em->flush();
}
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();
}
我解决了我的问题。我 post 我的代码也许会对某人有所帮助。
我的实体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;
}
}
我的实体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
形式
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
形式
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
]);
}
最后是我的控制器
$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');
}
成功了,是的 :) 谢谢大家。
我有下一个 table:测验、问题和 question_quiz。我有一个多对多的关系。 table 测验和问题的插入工作正常,但在 table question_quiz 中仅插入一条记录。
我的table
"question",没问题
+----+--------+
| id | title |
+----+--------+
| 61 | Title1 |
| 62 | Title2 |
| 63 | Title3 |
+----+--------+
"quiz",没问题
+----+-------+--------+
| id | name | status |
+----+-------+--------+
| 27 | Name1 | 0 |
+----+-------+--------+
"question_quiz"
+-------------+---------+
| question_id | quiz_id |
+-------------+---------+
| 61 | 27 |
+-------------+---------+
最后table必须插入61,62,63quiestion_id,但只能插入单条记录。
我的控制器片段。
$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();
}
问题实体的调用证据
$quiz->getQuestions()->add($question);
$question->addQuiz($quiz);
我用的是集合类型,可以插入任意数量的问题
更新测验类型表格。
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
]);
}
}
如果我调试方法 addQuestion()
我收到错误 INSERT INTO question (title) VALUES (?)' with params [null]。但是如果我调试方法 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 ▶}
}
调试 $form->get('questions')->getData() return
ArrayCollection {#733 ▼
-elements: array:2 [▼
0 => Question {#736 ▶}
1 => Question {#981 ▶}
]
}
没有 Quiz
和 Question
实体 - 很难说。但是
我认为问题出在您的控制器上。
$quiz = new Quiz();
$question = new Question();
//...
$question->addQuiz($quiz);
所以你创建了一个新的测验,它应该有多个问题,对吧? 但是你只分配了一次问题..
$question->addQuiz($quiz);
所以正确的方法应该是(有点冗长,这样你就明白了)
$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();
查看此示例 (https://gist.github.com/Ocramius/3121916),了解 ManyToMany 关系,特别是 addUSerGroup()
和 addUser()
方法。
在控制器(无表格)中尝试建议的方法,看看它是否有效,如果你得到超过一行 question_quiz
table
更新:
我认为您正在寻找的 "magic" 在您的测验实体中是 cascade={"persist"}
。看看这篇文章 (https://knpuniversity.com/screencast/collections/add-new-collection-cascade-persist)。尽管视频不是免费的,但文字很好。
1) 在您的实体
中设置cascade
2)更新了你 addQuestion()
测验 class 中的方法,如下所示
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) 获取嵌入集合以使用 prototype
=> http://symfony.com/doc/current/form/form_collections.html。这样您就可以随时添加新问题
4)提交后调用:
if ($form->isSubmitted() && $form->isValid()) {
$quiz = $form->getData();
$em->persist($quiz);
$em->flush();
}
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();
}
我解决了我的问题。我 post 我的代码也许会对某人有所帮助。
我的实体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;
}
}
我的实体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
形式
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
形式
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
]);
}
最后是我的控制器
$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');
}
成功了,是的 :) 谢谢大家。