我有两个实体,测验和题为OneToMany的关系(1个测验可以有很多问题)。
我正在尝试通过RestApi中的put操作更新测验对象(id = 19) 向数组问题中添加2个问题对象ID。 这些ID一直到该孤儿孤儿为止,他们的quiz_id为null。
测验ID 19更新前:
{
"id": 19
"alias": "Test Quiz",
"questions": [],
"hasFifty": false,
"hasTip": false,
"hasNext": false
}
Json放置数据操作(更新测验对象19):
{
"alias": "quiz-bill",
"questions": [42,43],
"hasFifty": true,
"hasTip": true,
"hasNext": true
}
放置请求的响应显示了更新测验对象:
{
"id": 19,
"alias": "quiz-bill",
"questions": [
{
"id": 42,
"content": "test test test",
"helpText": "dummy dummy dummy"
},
{
"id": 43,
"content": "test test",
"helpText": "dummy"
}
],
"hasFifty": true,
"hasTip": true,
"hasNext": true
}
但是这个对象是假的,当我从数据库中选择这些问题时,它们仍然具有quiz_id null。 我希望从parent(Quiz)更新中更新这些子对象的parent字段(quiz_id),但这似乎不可行。
有人在教义和Symfony框架上做了类似的事情吗?或者可以帮我吗?
测验实体:
/**
* Quiz.
*
* @ORM\Table(name="quiz")
* @ORM\Entity(repositoryClass="ApiBundle\Repository\QuizRepository")
* @JMS\ExclusionPolicy("all")
*/
class Quiz
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @JMS\Groups({"task", "quiz"})
* @JMS\Expose
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="alias", type="string", length=255)
* @JMS\Groups({"quiz"})
* @JMS\Expose
*/
private $alias;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Question", mappedBy="quiz")
* @JMS\Groups({"quiz"})
* @JMS\Expose
*/
private $questions;
/**
* @var bool
*
* @ORM\Column(name="hasFifty", type="boolean", nullable=true)
* @JMS\Groups({"quiz"})
* @JMS\Expose
*/
private $hasFifty;
/**
* @var bool
*
* @ORM\Column(name="hasTip", type="boolean", nullable=true)
* @JMS\Groups({"quiz"})
* @JMS\Expose
*/
private $hasTip;
/**
* @var bool
*
* @ORM\Column(name="hasNext", type="boolean", nullable=true)
* @JMS\Groups({"quiz"})
* @JMS\Expose
*/
private $hasNext;
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set alias.
*
* @param string $alias
*
* @return Quiz
*/
public function setAlias($alias)
{
$this->alias = $alias;
return $this;
}
/**
* Get alias.
*
* @return string
*/
public function getAlias()
{
return $this->alias;
}
/**
* Set hasFifty.
*
* @param bool $hasFifty
*
* @return Quiz
*/
public function setHasFifty($hasFifty)
{
$this->hasFifty = $hasFifty;
return $this;
}
/**
* Get hasFifty.
*
* @return bool
*/
public function getHasFifty()
{
return $this->hasFifty;
}
/**
* Set hasTip.
*
* @param bool $hasTip
*
* @return Quiz
*/
public function setHasTip($hasTip)
{
$this->hasTip = $hasTip;
return $this;
}
/**
* Get hasTip.
*
* @return bool
*/
public function getHasTip()
{
return $this->hasTip;
}
/**
* Add question.
*
* @param \ApiBundle\Entity\Question $question
*
* @return Quiz
*/
public function addQuestion(\ApiBundle\Entity\Question $question)
{
$this->questions[] = $question;
return $this;
}
/**
* Remove question.
*
* @param \ApiBundle\Entity\Question $question
*/
public function removeQuestion(\ApiBundle\Entity\Question $question)
{
$this->questions->removeElement($question);
}
/**
* Get questions.
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getQuestions()
{
return $this->questions;
}
/**
* Set hasNext.
*
* @param bool $hasNext
*
* @return Quiz
*/
public function setHasNext($hasNext)
{
$this->hasNext = $hasNext;
return $this;
}
/**
* Get hasNext.
*
* @return bool
*/
public function getHasNext()
{
return $this->hasNext;
}
}
问题实体:
/**
* Question.
*
* @ORM\Table(name="question")
* @ORM\Entity(repositoryClass="ApiBundle\Repository\QuestionRepository")
* @JMS\ExclusionPolicy("all")
*/
class Question
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @JMS\Groups({"quiz" ,"question"})
* @JMS\Expose
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="content", type="text")
* @JMS\Groups({"quiz" ,"question"})
* @JMS\Expose
*/
private $content;
/**
* @var string
*
* @ORM\Column(name="help", type="text", nullable=true)
* @JMS\Groups({"quiz" ,"question"})
* @JMS\Expose
*/
private $helpText;
/**
* @var \ApiBundle\Entity\Quiz
*
* @ORM\ManyToOne(targetEntity="Quiz", inversedBy="questions")
* @ORM\JoinColumn(name="quiz_id", referencedColumnName="id")
*/
protected $quiz;
/**
* @var \DateTime
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(name="createdAt", type="datetime")
* @JMS\Groups({"quiz" ,"question"})
* @JMS\Expose
*/
private $createdAt;
/**
* @var \DateTime
*
* @Gedmo\Timestampable(on="update")
* @ORM\Column(name="updatedAt", type="datetime", nullable=true)
* @JMS\Groups({"quiz" ,"question"})
* @JMS\Expose
*/
private $updatedAt;
public function __construct()
{
$this->answers = new ArrayCollection();
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set content.
*
* @param string $content
*
* @return Question
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content.
*
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set createdAt.
*
* @param \DateTime $createdAt
*
* @return Question
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt.
*
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt.
*
* @param \DateTime $updatedAt
*
* @return Question
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt.
*
* @return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set helpText.
*
* @param string $helpText
*
* @return Question
*/
public function setHelpText($helpText)
{
$this->helpText = $helpText;
return $this;
}
/**
* Get helpText.
*
* @return string
*/
public function getHelpText()
{
return $this->helpText;
}
/**
* Set quiz.
*
* @param \ApiBundle\Entity\Quiz $quiz
*
* @return Question
*/
public function setQuiz(\ApiBundle\Entity\Quiz $quiz = null)
{
$this->quiz = $quiz;
return $this;
}
/**
* Get quiz.
*
* @return \ApiBundle\Entity\Quiz
*/
public function getQuiz()
{
return $this->quiz;
}
}
QuizController放置动作:
/**
* Update an existing Quiz.
*
* @param Request $request
* @param int $id
*
* @return mixed
*
* @Operation(
* tags={"Quiz"},
* summary="Update an existing Quiz.",
* @SWG\Response(
* response="204",
* description="Returned when an existing Quiz has been successful updated"
* ),
* @SWG\Response(
* response="400",
* description="Return when errors"
* ),
* @SWG\Response(
* response="401",
* description="Returned when access is not authorized"
* ),
* @SWG\Response(
* response="404",
* description="Return when not found"
* )
* )
*
*
* @Rest\View(serializerGroups={"quiz"})
*/
public function putAction(Request $request, $id)
{
$quiz = $this->getDoctrine()->getRepository('ApiBundle:Quiz')->find($id);
if (null === $quiz || empty($quiz)) {
return new View(null, Response::HTTP_NOT_FOUND);
}
$form = $this->createForm(QuizType::class, $quiz, [
'method' => 'PUT',
'csrf_protection' => false,
]);
$form->submit($request->request->all(), false);
if (!$form->isValid()) {
return $form;
}
$em = $this->getDoctrine()->getManager();
$em->persist($quiz);
$em->flush();
return $quiz;
}
QuizType表单:
<?php
namespace ApiBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class QuizType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('alias')
->add('hasFifty')
->add('hasTip')
->add('hasNext')
->add('videoUrl')
->add('questions')
->add('task');
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ApiBundle\Entity\Quiz',
'csrf_protection' => false,
'allow_extra_fields' => true,
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'apibundle_quiz';
}
}
答案 0 :(得分:0)
在控制器操作中,您仅保留Quiz实体,但也需要保留相关的Question实体。在多对一关系中,连接保存在只能有一个相关实体的实体表中。
foreach($quiz->getQuestions() as $question) {
// I don't know if you need this line
$question->setQuiz($quiz);
$em->persist($question);
}
$em->persist($quiz);
答案 1 :(得分:0)
在将已经存在的问题添加到测验中时,您无需级联持久化,但仍需要将测验设置为添加的问题:
// inside Quiz entity
public function addQuestion(\ApiBundle\Entity\Question $question)
{
$question->setQuiz($this);
$this->questions[] = $question;
return $this;
}
这是因为(引自Doctrine ORM Documentation)
Doctrine只会检查关联的拥有方 变化。
仅对关联的反面所做的更改将被忽略。 确保更新双向关联的两端(或在 从教义的角度来看,至少是拥有方)
在您的情况下,关联的相反方面是Quiz
实体,而拥有方面是Question
实体。