OneToMany отношения NULL как внешний ключ? - PullRequest
0 голосов
/ 19 февраля 2019

Преамбула


Я пытаюсь POST ( вставить в базу данных Postgresql ) отформатированный объект JSON, преобразованный в объект PHP, благодаря FOSRestBundle маршрут с JMSSerializerBundle .Эта сущность выглядит следующим образом:

**Vote** : OneToOne Bidirectional : **Question** : OneToMany Bidirectional : Answer

Полезная нагрузка JSON здесь:

{
  "title": "string",
  "description": "string",
  "question": {
    "id": 0,
    "title": "string",
    "description": "string",
    "answers": [
      {
        "title": "string",
        "description": "string"
      },
      {
        "title": "First answer ?",
        "description": "string"
      }
    ]
  }
}

Проблема


Когда вставляется голос, vote_id в поле вопроса равно нулю, равно как question_id в ответах.

Когда я получаю полезную нагрузку с моего маршрута, она преобразуется в объект с fos_rest.request_body, вот действие:

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

Я получаю объект голосования с моими вопросами и ответами, но когда он вставляется в базу данных, как указано выше, поля внешних ключей имеют значение NULL.

То, что я уже сделал


Я посмотрел на отношения и посмотрел, есть ли персистентность в сущностях 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;

Я использовал php bin\console make:entity --regenerate, чтобы получить все методы получения / установки.Я очистил базу данных и восстановил ее.

Ответ


Как сказал @yTko, я забыл поместить ссылки на мой объект в моем контроллере, я думал, что это было сделано Doctrineс сохранением, так вот мой рабочий код:

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

1 Ответ

0 голосов
/ 19 февраля 2019

Я думаю, что вы просто забыли задать похожие случаи голосования и задать вопросы.

В вашем действии контроллера у вас есть объект голосования, преобразованный в jms из вашего примера json.

Итак, вам нужно установить их вручную, вызвав определенные сеттеры, например:

$question = $vote->getQuestion();
$question->setVote($vote);

или изменить ваши сеттеры следующим образом:

public function setQuestion(Question $question)
{
    $this->question = $question;
    $this->question->setVote($this);

    return $this;
}

Я предпочитаюПервый способ, потому что сеттеры предназначены только для установки конкретных значений, а не для изменения других объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...