I'm trying to POST (insert in a Postgresql database) a JSON formatted entity converted into a PHP object thanks to a FOSRestBundle route with JMSSerializerBundle. This entity looks like this:
**Vote** : OneToOne Bidirectional : **Question** : OneToMany Bidirectional : Answer
The JSON payload here :
{
"title": "string",
"description": "string",
"question": {
"id": 0,
"title": "string",
"description": "string",
"answers": [
{
"title": "string",
"description": "string"
},
{
"title": "First answer ?",
"description": "string"
}
]
}
}
When it inserts the vote, the vote_id
in the question field is null as well as the question_id
in answers.
When I get the payload from my route it get transformed into an object with the fos_rest.request_body
here is the action :
public function postVoteAction(Vote $vote, ConstraintViolationList $violations)
{
if (count($violations)) {
return $this->view($violations, Response::HTTP_BAD_REQUEST);
}
$em = $this->getDoctrine()->getManager();
$vote->setOwner($this->getUser());
$em->persist($vote);
$em->flush();
return $vote;
}
I do get a Vote object with my question and answers but when it get inserted in the database as said earlier foreign key fields are NULL.
I looked into relations & looked if persist was there in entities cascade={"persist"}
// in vote
@ORM\OneToOne(targetEntity="Question", mappedBy="vote", cascade={"persist", "remove"})
private $question;
// in question
@ORM\OneToOne(targetEntity="Vote", inversedBy="question", cascade={"persist"})
@ORM\JoinColumn(name="vote_id", referencedColumnName="id")
private $vote;
@ORM\OneToMany(targetEntity="Answer", mappedBy="question", cascade={"persist", "remove"})
private $answers;
// in answer
@ORM\ManyToOne(targetEntity="Question", inversedBy="answers", cascade={"persist"})
@ORM\JoinColumn(name="question_id", referencedColumnName="id")
private $question;
I used php bin\console make:entity --regenerate
to get all
getters/setters.
I cleared the database & regenerated it.
As said by @yTko I forgot to put the references back to my object in my controller I thought that it was made by Doctrine with the persist so here is now my working code :
public function postVoteAction(Vote $vote, ConstraintViolationList $violations)
{
if (count($violations)) {
return $this->view($violations, Response::HTTP_BAD_REQUEST);
}
$em = $this->getDoctrine()->getManager();
$vote->setOwner($this->getUser());
$question = $vote->getQuestion();
$question->setVote($vote);
foreach ($question->getAnswers() as $answer) {
$answer->setQuestion($question);
}
$em->persist($vote);
$em->flush();
return $vote;
}
I think that you've just forgotten to set related instances of vote and questions.
In your controller action you have the vote object that converted by jms with from your json example.
So, you need to set them manually through calling certain setters, like this:
$question = $vote->getQuestion();
$question->setVote($vote);
or modify your setters this way:
public function setQuestion(Question $question)
{
$this->question = $question;
$this->question->setVote($this);
return $this;
}
I prefer the first way because setters is just for setting concrete values, not for modifying other objects.