core
core copied to clipboard
Unique constraint violation on put
API Platform version(s) affected: 3.1.8
Description
When you try to update an API Resource that contains a doctrine collection of Entities that are not an API Resource and define a Unique Index, the update will fail since it will try to recreate the collection entities.
How to reproduce
Have like this entities:
#[Entity]
#[ApiResource]
class Foo {
// ...
#[OneToMany(mappedBy: 'foo', targetEntity: Bar::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[Valid]
private Collection $bars;
public function getBars(): Collection
{
return $this->bars;
}
public function setBars(Collection $bars): Foo
{
$this->bars = $bars;
return $this;
}
public function addBar(Bar $bar): Foo
{
if (!$this->bars->contains($bar)) {
$bar->foo($this);
$this->bars->add($bar);
}
return $this;
}
public function removeBar(Bar $bar): Foo
{
if ($this->bars->contains($bar)) {
$this->bars->removeElement($bar);
}
return $this;
}
}
and
#[Entity]
#[UniqueConstraint(fields: ['foo', 'barType'])]
#[UniqueEntity(fields: ['foo', 'barType'])]
class Bar {
#[ManyToOne(targetEntity: BarType::class)]
#[JoinColumn(nullable: false, onDelete: 'CASCADE')]
private BarType $barType;
#[ManyToOne(targetEntity: Foo::class, inversedBy: 'bars')]
#[JoinColumn(nullable: false, onDelete: 'CASCADE')]
#[Ignore]
private Foo $foo;
private string $barVal;
//...
}
and
#[Entity]
#[ApiResource]
#[Get]
#[GetCollection]
class BarType {
//...
}
If you then try to make a PUT request with a payload that already contains a Bar
{
"@id": "/api/foos/1"
"@type": "Foo"
"id": 1,
"bars": [
{
"barType": "/api/bar_types/1"
"barVal": "Test"
}
]
}
element it will always result in a constraint violation since it'll try to re-create the Bar
Possible Solution
Optimally Api Platform would not need to recreate the non Api Resource entities, that would fix it.