【问题标题】:OneToMany relationship NULL as the foreign key?OneToMany 关系 NULL 作为外键?
【发布时间】:2019-02-19 18:22:33
【问题描述】:

序言


我正在尝试发布(在 Postgresql 数据库中插入)一个 JSON 格式的实体,这要归功于带有 JMSSerializerBundleFOSRestBundle 路由。该实体如下所示:

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

我确实得到了一个带有我的问题和答案的 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;
}

【问题讨论】:

  • 任何人都可以爬过很多代码。请将其缩减为 Minimal, Complete and Verifiable Example 并将代码包含在您的问题中。
  • 请向我们展示定义实体之间关系的注释。
  • @Zak 添加了他们。

标签: php postgresql symfony doctrine-orm fosrestbundle


【解决方案1】:

我认为您只是忘记设置相关的投票和问题实例。

在您的控制器操作中,您拥有由 jms 与您的 json 示例转换的投票对象。

因此,您需要通过调用某些 setter 手动设置它们,如下所示:

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

或以这种方式修改您的设置器:

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

    return $this;
}

我更喜欢第一种方式,因为 setter 只是用于设置具体值,而不是用于修改其他对象。

【讨论】:

  • 所以我的答案也必须这样做?
  • 是的,对于你所有的嵌套。因为 jms 只是将 json 映射到实体对象上,仅此而已。另外,您可以尝试jmsyst.com/libs/serializer/master/reference/… 方法并在其中设置您的关系,但如果您没有魔杖,我不建议像其他任何魔法一样使用它
猜你喜欢
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
  • 1970-01-01
  • 2022-12-02
  • 1970-01-01
相关资源
最近更新 更多