Doctrine Mongo ODM merge for externally modified data-Collection of common programming errors
I’m writing a Symfony2 app that allows mobile users to create and update “Homes” via a REST service. I’m using MongoDB as the storage layer and Doctrine MongoDB ODM to do the Document handling.
The GET /homes/{key}
and POST /homes
methods are working fine. The problem comes when I attempt to update an existing Home with PUT /homes/{key}
.
Here’s the current code:
/**
* PUT /homes/{key}
*
* Updates an existing Home.
*
* @param Request $request
* @param string $key
* @return Response
* @throws HttpException
*/
public function putHomeAction(Request $request, $key)
{
// check that the home exists
$home = $this->getRepository()->findOneBy(array('key' => (int) $key));
// disallow create via PUT as we want to generate key ourselves
if (!$home) {
throw new HttpException(403, 'Home key: '.$key." doesn't exist, to create use POST /homes");
}
// create object graph from JSON string
$updatedHome = $this->get('serializer')->deserialize(
$request->getContent(), 'Acme\ApiBundle\Document\Home', 'json'
);
// replace existing Home with new data
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$home = $dm->merge($updatedHome);
$dm->flush();
$view = View::create()
->setStatusCode(200)
->setData($home);
$response = $this->get('fos_rest.view_handler')->handle($view);
$response->setETag(md5($response->getContent()));
$response->setLastModified($home->getUpdated());
return $response;
}
The JSON string passed to the action is successfully deserialized to my Document object graph by JMSSerializer, but when I attempt the merge & flush, I get the error:
Notice: Undefined index: in ..../vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataInfo.php line 1265
I’ve been attempting to follow the documentation here: http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/working-with-objects.html#merging-documents
Is there something I need to do to the deserialized Home before attempting to merge it? Is merge the wrong method?
Thanks.
-
The only way I found to do this is to create a method in your document class that takes the updated document (e.g.
$updatedHome
) as a parameter and then just copies the required fields over into the existing document (e.g.$home
).So above, the code:
// replace existing Home with new data $dm = $this->get('doctrine.odm.mongodb.document_manager'); $home = $dm->merge($updatedHome); $dm->flush();
can be replaced with:
// replace existing Home with new data $home->copyFromSibling($updatedHome); $this->getDocumentManager()->flush();
and then it will work.
Originally posted 2013-11-27 12:01:52.