首页 > 解决方案 > API 平台:PUT 与连接表的级联选项

问题描述

我正在使用带有 API 平台和 Doctrine 的 Symfony 5。我有一个“Source”实体和一个“SourceContributor”连接表,其中包含关系的附加信息。

资源:

/**
 * ...
 *
 * @ORM\Entity()
 */
class Source
{
    // ...

    /**
     * @Groups({"source:read", "source:write"})
     * @ORM\OneToMany(targetEntity="SourceContributor",  mappedBy="source", cascade={"persist", "merge"}, orphanRemoval=true)
     */
    private Collection $contributors;

    public function getContributors(): Collection
    {
        return $this->contributors;
    }

    public function addContributor(SourceContributor $contributor): self
    {
        if (!$this->contributors->contains($contributor)) {
            $contributor->setSource($this);
            $this->contributors[] = $contributor;
        }

        return $this;
    }

    public function removeContributor(SourceContributor $contributor): self
    {
        if ($this->contributors->contains($contributor)) {
            $this->contributors->removeElement($contributor);
        }

        return $this;
    }

    public function __construct()
    {
        $this->contributors = new ArrayCollection();
    }
}

来源贡献者:

/**
 * @ORM\Entity
 */
class SourceContributor
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\ManyToOne(targetEntity="Source", inversedBy="contributors")
     */
    private ?Source $source;

    public function getSource(): ?Source
    {
        return $this->source;
    }

    public function setSource(?Source $source): self
    {
        $this->source = $source;
        return $this;
    }


    /**
     * @Groups({"source:read", "source:write"})
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\ManyToOne(targetEntity="Contributor")
     */
    private ?Contributor $contributor;

    public function getContributor(): ?Contributor
    {
        return $this->contributor;
    }

    public function setContributor(?Contributor $contributor): self
    {
        $this->contributor = $contributor;
        return $this;
    }


    /**
     * @Groups({"source:read", "source:write"})
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\Column(type="smallint", nullable=false, options={"unsigned"=true})
     */
    private ?int $role;

    public function getRole(): ?int
    {
        return $this->role;
    }

    public function setRole(int $role): self
    {
        $this->role = $role;
        return $this;
    }
}

像这样通过 POST 创建我的 Source 实体可以正常工作:

{
  "contributors": [
    {
      "contributor": "/contributors/1",
      "role": 0
    },
    {
      "contributor": "/contributors/1",
      "role": 1
    }
  ]
}

但是,在创建实体后,通过 PUT 以相同的方式更新它不起作用。

使用参数 [0, 4, 1] 执行“INSERT INTO source_contributor (role, source_id,contributor_id) VALUES (?, ?, ?)”时发生异常:

SQLSTATE [23000]:违反完整性约束:1062 键 'PRIMARY' 的重复条目 '4-1-0'

Doctrine 似乎试图再次插入 SourceContributor。有谁知道解决方案?

标签: symfonydoctrine-ormdoctrineapi-platform.com

解决方案


发生这种情况是因为您传递了一个对象,如果您不需要创建新的 source_contributor,则必须传递一个 URI。代替

{
  "contributors": [
    {
      "contributor": "/contributors/1",
      "role": 0
    }
  ]
}

至:

{
  "contributors": [
    "/contributors/1"
  ]
}

推荐阅读