We are using Symfony2 to create an API. When updating a record, we expect the JSON input to represent a serialized updated entity. The JSON data will not contain some fields (for instance, CreatedAt should be set only once when the entity is created - and never updated). For instance, here is an example JSON PUT request:
{"id":"1","name":"anyname","description":"anydescription"}
Here is the PHP code on the Controller that should update the entity according to the JSON above (we are using JMS serializer Bundle):
$supplier = $serializer->deserialize(
$this->get('request')->getContent(),
'WhateverEntity',
'json'
);
The EntityManger understands (correctly) that this is an update request (in fact, a SELECT query is implicitly triggered). The EntityManager also guess (not correctly) that CreatedAt property should be NULLified - it should instead keep the previous one.
How to fix this issue?
using the JMSSerializerBundle follow the install instructions at http://jmsyst.com/bundles/JMSSerializerBundle
either create your own serializer service or alter the JMSSerializerBundle to use the doctrine object constructor instead of the simple object constructor.
<service id="jms_serializer.object_constructor" alias="jms_serializer.doctrine_object_constructor" public="false"/>
This basically handles exactly what Ocramius solution does but using the JMSSerializerBundles deserialize.
It's possible as well to do it with Symfony Serializer using object_to_populate option.
Example: I receive JSON request. If record exists in database I want to update fields received in body, if it does not exist I want to create new one.
/**
* @Route("/{id}", methods={"PUT"})
*/
public function upsert(string $id, Request $request, SerializerInterface $serializer)
{
$content = $request->getContent(); // Get json from request
$product = $this->getDoctrine()->getRepository(Product::class)->findOne($id); // Try to find product in database with provided id
if (!$product) { // If product does not exist, create fresh entity
$product = new Product();
}
$product = $serializer->deserialize(
$content,
Product::class,
'json',
['object_to_populate' => $product] // Populate deserialized JSON content into existing/new entity
);
// validation, etc...
$this->getDoctrine()->getManager()->persist($product); // Will produce update/instert statement
$this->getDoctrine()->getManager()->flush($product);
// (...)
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