I have a Symfony rest api build with fos restbundle and I'm deserializing a json PUT request in order to update a doctrine entity with a to-many relation.
However, the to-many child objects which are configured with orphanremoval=true
does not get removed from the database when they are not present in the json data.
The PUT request payload:
{
"id": 1,
"name":"Some name",
"export_destinations": [
{
"id": 1,
"type": "USER_STORAGE",
"user": {"id": 5}
}
{
"id": 2,
"type": "SYSTEM_STORAGE"
}
]
}
The controller action:
/**
* @Rest\Put("{id}")
* @ParamConverter(
* "exportJob",
* converter="fos_rest.request_body",
* options={"deserializationContext"={"groups"={"put"}}}
* )
* @Rest\View(serializerGroups={"details"})
* @param ExportJob $exportJob
* @return ExportJob
*/
public function putAction(ExportJob $exportJob)
{
$this->getManager()->persist($exportJob);
$this->getManager()->flush();
return $exportJob;
}
ExportJob entity
/**
* @ORM\Entity()
*/
class ExportJob
{
/**
* @var ArrayCollection|ExportDestination[]
*
* @ORM\OneToMany(targetEntity="ExportDestination", mappedBy="exportJob", cascade={"persist", "remove", "merge"}, orphanRemoval=true)
*/
protected $exportDestinations;
/**
* @param ExportDestination $exportDestination
* @return $this
*/
public function addExportDestination(ExportDestination $exportDestination)
{
$exportDestination->setExportJob($this);
$this->exportDestinations->add($exportDestination);
return $this;
}
/**
* @param ExportDestination $exportDestination
* @return $this
*/
public function removeExportDestination(ExportDestination $exportDestination)
{
$this->exportDestinations->removeElement($exportDestination);
$exportDestination->setExportJob(null);
return $this;
}
}
JMS meta data
MyProject\ExportBundle\Entity\ExportJob:
exclusion_policy: ALL
properties:
id:
groups: ['list', 'details', 'put']
expose: true
name:
groups: ['list', 'details', 'put', 'patch', 'post']
expose: true
exportDestinations:
groups: ['details', 'put', 'patch', 'post']
expose: true
type: 'ArrayCollection<MyProject\ExportBundle\Entity\ExportDestination>'
I am using the DoctrineObjectConstructor
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
Now when I leave out the second object from the export_destinations array in the json payload my exportJob in the controller action has only one exportDestination object in the array collection after deserialization.
But when I persist, I expect doctrine to remove the exportDestination from the database since I have orphanremoval=true
.
What I think the problem is, is that the removeExportDestination()
method never gets called during deserialization what should set the relation to null on the inversed side. If that doesn't happen it will not delete the entity since it's not become an orphan yet.
Is there a way that JMS will use the add/remove methods for ArrayCollections during deserialization?
I've also tried to use merge()
instead of persist()
but did not make any difference