I'm using Symfony 5 with API Platform and Doctrine. I have a "Source" entity and a "SourceContributor" join table, which contains additional info for the relation.
Source:
/**
* ...
*
* @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();
}
}
SourceContributor:
/**
* @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;
}
}
Creating my Source entity via POST like this works fine:
{
"contributors": [
{
"contributor": "/contributors/1",
"role": 0
},
{
"contributor": "/contributors/1",
"role": 1
}
]
}
However, after the entity is created, updating it the same way via PUT does not work.
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 seems to be trying to insert the SourceContributor again. Does anyone know a solution?
It happens because you pass an object, if you don't need to create a new source_contributor, you have to pass a URI. Replace
{
"contributors": [
{
"contributor": "/contributors/1",
"role": 0
}
]
}
to:
{
"contributors": [
"/contributors/1"
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With