API Platform version(s) affected: 2.6.3, 2.6.2, 2.6.1, 2.6.0.
Description
I think there is a BC break with the setting of the option deep_object_to_populate to true in here:
// /src/Serializer/SerializerContextBuilder.php
if ($context['api_allow_update'] && 'PATCH' === $method) {
$context['deep_object_to_populate'] = $context['deep_object_to_populate'] ?? true;
}
Before this, the code behaved as this option was false therefore it always created nested objects. Now if there is already another object in place, it will try to update it.
I am not against the change itself if it is wanted. I was suprised by the change in the default behavior happening in a minor version and I simply think it should have been put more forward.
In the related entry in changelog:
PATCH: Support patching deep objects (#3847)
There is no mention of such change in default behavior.
How to reproduce (Minimal test case)
Given the following classes:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity
*
* @ApiResource(attributes={
* "normalization_context"={"groups"={"read"}},
* "denormalization_context"={"groups"={"write"}}
* })
*/
class Foo {
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @Groups({"read"})
*/
public $id;
/**
* @var Bar
*
* @ORM\ManyToOne(targetEntity=Bar::class, cascade={"persist"})
*
* @Groups({"write", "read"})
*/
public Bar $bar;
public function __construct (Bar $bar) {
$this->bar = $bar;
}
public function getBar()
{
return $this->bar;
}
public function setBar(Bar $bar)
{
$this->bar = $bar;
}
}
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity
*
* @ApiResource(attributes={
* "normalization_context"={"groups"={"read"}},
* "denormalization_context"={"groups"={"write"}}
* })
*/
class Bar {
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @Groups({"read"})
*/
public $id;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"write", "read"})
*/
public string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
Given the following chain of requests :
Request
POST /foos
{
"bar": {
"name": "1st"
}
}
Request:
{
"@context": "/api/contexts/Foo",
"@id": "/api/foos/10",
"@type": "Foo",
"id": 10,
"bar": {
"@id": "/api/bars/10",
"@type": "Bar",
"id": 10,
"name": "1st"
}
}
Request:
PATCH /api/foos/10
{
"bar": {
"name": "2nd"
}
}
Response:
In 2.5.10:
{
"@context": "/api/contexts/Foo",
"@id": "/api/foos/10",
"@type": "Foo",
"id": 10,
"bar": {
"@id": "/api/bars/11",
"@type": "Bar",
"id": 11,
"name": "2nd"
}
}
As you can see, there is a creation of a new resource.
In 2.6.3:
{
"@context": "/api/contexts/Foo",
"@id": "/api/foos/10",
"@type": "Foo",
"id": 10,
"bar": {
"@id": "/api/bars/10",
"@type": "Bar",
"id": 10,
"name": "2nd"
}
}
As you can see, there is an update of the existing resource.
Possible Solution
Workaround : Create a service implementing SerialiserContextBuilderInterface to override this change.
API Platform version(s) affected: 2.6.3, 2.6.2, 2.6.1, 2.6.0.
Description
I think there is a BC break with the setting of the option deep_object_to_populate to true in here:
// /src/Serializer/SerializerContextBuilder.phpBefore this, the code behaved as this option was false therefore it always created nested objects. Now if there is already another object in place, it will try to update it.
I am not against the change itself if it is wanted. I was suprised by the change in the default behavior happening in a minor version and I simply think it should have been put more forward.
In the related entry in changelog:
There is no mention of such change in default behavior.
How to reproduce (Minimal test case)
Given the following classes:
Given the following chain of requests :
Request
POST /foos
Request:
Request:
Response:
In 2.5.10:
As you can see, there is a creation of a new resource.
In 2.6.3:
As you can see, there is an update of the existing resource.
Possible Solution
Workaround : Create a service implementing
SerialiserContextBuilderInterfaceto override this change.