2012-01-04 13 views
8

Estamos utilizando Symfony2 para crear una API. Al actualizar un registro, esperamos que la entrada JSON represente una entidad actualizada serializada. Los datos JSON no contendrán algunos campos (por ejemplo, CreatedAt debe establecerse solo una vez cuando se crea la entidad, y nunca se actualiza). Por ejemplo, aquí hay un ejemplo de solicitud JSON PUT:¿Cómo actualizar una entidad Doctrine desde un JSON serializado?

{"id":"1","name":"anyname","description":"anydescription"} 

Este es el código PHP en el controlador que debe actualizar la entidad de acuerdo con el JSON anterior (estamos utilizando JMS serializador Bundle):

$supplier = $serializer->deserialize(
    $this->get('request')->getContent(), 
    'WhateverEntity', 
    'json' 
); 

EntityManger entiende (correctamente) que se trata de una solicitud de actualización (de hecho, una consulta SELECT se activa de forma implícita). El EntityManager también adivina (no correctamente) que la propiedad CreatedAt debe ser NULLified, sino que debe mantener la anterior.

¿Cómo solucionar este problema?

Respuesta

8

Utilizaría la API Doctrine\ORM\Mapping\ClassMetadata para descubrir los campos existentes en su entidad. Puede hace el siguiente (no sé cómo funciona JMSSerializerBundle):

//Unserialize data into $data 
$metadata = $em->getMetadataFactory()->getMetadataFor($FQCN); 
$id = array(); 
foreach ($metadata->getIdentifierFieldNames() as $identifier) { 
    if (!isset($data[$identifier])) { 
     throw new InvalidArgumentException('Missing identifier'); 
    } 
    $id[$identifier] = $data[$identifier]; 
    unset($data[$identifier]); 
} 
$entity = $em->find($metadata->getName(), $id); 
foreach ($metadata->getFieldNames() as $field) { 
    //add necessary checks about field read/write operation feasibility here 
    if (isset($data[$field])) { 
     //careful! setters are not being called! Inflection is up to you if you need it! 
     $metadata->setFieldValue($entity, $field, $data[$field]); 
    } 
} 
$em->flush(); 
14

utilizando el JMSSerializerBundle siga las instrucciones de instalación en http://jmsyst.com/bundles/JMSSerializerBundle

o bien crear su propio servicio de serializador o alterar el JMSSerializerBundle utilizar el doctrine object constructor en lugar del simple constructor de objetos.

<service id="jms_serializer.object_constructor" alias="jms_serializer.doctrine_object_constructor" public="false"/> 

Esto básicamente maneja exactamente lo que hace la solución Ocramius pero utilizando los JMSSerializerBundles deserializar.

Cuestiones relacionadas