API 平台:PUT 加入级联选项 table

API Platform: PUT with cascade option for join table

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

来源:

/**
 * ...
 *
 * @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 创建我的源实体工作正常:

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

但是,创建实体后,通过 PUT 以同样的方式更新它是行不通的。

An exception occurred while executing 'INSERT INTO source_contributor (role, source_id, contributor_id) VALUES (?, ?, ?)' with params [0, 4, 1]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '4-1-0' for key 'PRIMARY'

Doctrine 似乎正在尝试再次插入 SourceContributor。 有人知道解决方案吗?

它发生是因为你传递了一个对象,如果你不需要创建一个新的source_contributor,你必须传递一个URI。 替换

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

至:

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