У меня есть сборка Symfony rest api с fos restbundle, и я десериализую запрос JSON PUT, чтобы обновить объект доктрины с отношением ко многим.
Однако дочерние объекты для многих, настроенные с помощью orphanremoval=true, не удаляются из базы данных, если они не присутствуют в данных json.
Полезные данные запроса PUT:
{
"id": 1,
"name":"Some name",
"export_destinations": [
{
"id": 1,
"type": "USER_STORAGE",
"user": {"id": 5}
}
{
"id": 2,
"type": "SYSTEM_STORAGE"
}
]
}
Действие контроллера:
/**
* @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
/**
* @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
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>'
Я использую DoctrineObjectConstructor
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
public: false
Теперь, когда я оставляю второй объект из массива export_destinations в полезной нагрузке json, мой exportJob в действии контроллера имеет только один объект exportDestination в коллекции массивов после десериализации.
Но когда я упорствую, я ожидаю, что доктрина удалит exportDestination из базы данных, поскольку у меня есть orphanremoval=true.
Я думаю, проблема в том, что метод removeExportDestination() никогда не вызывается во время десериализации, что должно установить отношение к нулю на обратной стороне. Если этого не произойдет, он не удалит объект, поскольку он еще не стал сиротой.
Есть ли способ, которым JMS будет использовать методы добавления / удаления для ArrayCollections во время десериализации?
Я также пробовал использовать merge() вместо persist(), но без разницы





Вы правы в том, что «метод removeExportDestination () никогда не вызывается во время десериализации».
Вы можете определить свойство аксессуар, чтобы делать то, что вы хотите:
exportDestinations:
groups: ['details', 'put', 'patch', 'post']
expose: true
type: 'ArrayCollection<AppBundle\Entity\ExportDestination>'
accessor:
getter: "getExportDestinations"
setter: "setExportDestinations"
и в сущности ExportJob:
public function getExportDestinations()
{
return $this->exportDestinations;
}
public function setExportDestinations($exportDestinations)
{
// first detach existing related entities.
foreach ($this->exportDestinations as $exportDestination) {
$exportDestination->setExportJob(null);
}
$this->exportDestinations = $exportDestinations;
foreach ($exportDestinations as $exportDestination) {
$exportDestination->setExportJob($this);
}
}
так что во время десериализации вызывается "setExportDestinations", который заботится об удалении связи.
Сказав это, я не уверен, следует ли вам использовать orphanremoval=true в отношении, поскольку
orphanRemoval=true, even if you will remove given ExportDestination from one ExportJob, and then attach to another ExportJob, this ExportDestination will be deleted during persist, because the reference has been deleted.
Я бы посоветовал удалить его и найти другой способ удаления "сиротских" сущностей ExportDestination.
Можете ли вы добавить код объекта ExportDestination и его метаданные jms?