2012-02-16 18 views
6

Antecedentes:Manipulación de datos de la POST para trabajar con formas de Symfony2 cuando se utiliza en una API REST

Estoy escribiendo una API REST de Symfony. Quiero que el cliente pueda publicar en una url usando el tipo de contenido application/json y publicar un objeto json del formulario que la acción del controlador está buscando.

Im usando una configuración de controlador bastante básico para esto. Vamos a suponer con fines de demostración que estoy tratando de autenticar un simple combo de contraseña de usuario.

public function loginAction(Request $request) 
{ 
    $user = new ApiUser(); 
    $form = $this->createForm(new ApiUserType(), $user); 
    if ("POST" == $request->getMethod()) { 
     $form->bindRequest($request); 
     if ($form->isValid()) { 
      $em = $this->getDoctrine()->getEntityManager(); 
      $repo = $this->getDoctrine()->getRepository('ApiBundle:ApiUser'); 
      $userData = $repo->findOneByUsername($user->getUsername()); 
      if (is_object($userData)) { 
       /** do stuff for authenticating **/ 
      } 
      else{ 
       return new Response(json_encode(array('error'=>'no user by that username found'))); 
      } 
     else{ 
      return new Response(json_encode(array('error'=>'invalid form'))); 
     } 
    } 
} 

Ahora el problema que tengo, y tienen que he intentado var_dumping esto hasta que las vacas vuelvan a casa, es que por cualquier razón Symfony no quiere tomar la application/json contenido cuerpo y utilizar esos datos para llenar los datos del formulario.

Nombre del formulario: api_apiuser

campos: nombre de usuario, contraseña

¿Cuál sería la mejor manera de manejar este tipo de tarea. Estoy abierto a sugerencias, siempre y cuando pueda hacerlo funcionar. Gracias por su tiempo con el asunto.

Respuesta

5

he encontrado realmente una manera similar a solucionar este problema, después de comprobar si el método es post y antes de vincular la solicitud al formulario hago esto:

if ("POST" === $request->getMethod()) { 
    if (0 === strpos($request->headers->get('Content-Type'), 'application/json')){ 
     $data = json_decode($request->getContent(), true); 
     $request->request->replace(is_array($data) ? $data : array()); 
    } 
    $form->bindRequest($request); 
    /** Rest of logic **/ 
} 
6

Deberá acceder al cuerpo de la solicitud RAW y luego usar json_decode. Youll probablemente tendrá que cambiar su método bindRequest a algo como lo siguiente:

public function bindRequest(Request $request) 
{ 
     if($request->getFormat() == 'json') { 
      $data = json_decode($request->getContent()); 
      return $this->bind($data); 
     } else { 
      // your standard logic for pulling data form a Request object 
      return parent::bind($request); 
     } 
} 

realmente no he metido con SF2 sin embargo, por lo que este es adivinar basan más en la API, exp. con sf1.x y las cosas se obtienen de las presentaciones en el marco. También podría ser mejor hacer un método completamente diferente como bindJsonRequest, así que las cosas están un poco más ordenadas.

2

Sí, lo que el formulario está esperando durante el enlace es una matriz que contiene claves que corresponden a sus propiedades ApiUser.

Así que si usted envía una solicitud POST con la cadena:

{ username: 'user', password: 'pass' } 

que tendrá que transformarlo en una matriz mediante json_decode por ejemplo:

$data = json_decode($request->getContent()); // $request->request->get('json_param_name'); 

A continuación, se unen esta matriz a la formulario usando $form->bind($data);

El formulario actualizará sus propiedades de ApiUser correspondientes a las claves de la matriz (nombre de usuario, contraseña).

Si usted está construyendo una API REST JSON, yo aconsejaría a automatizar este proceso utilizando serializadores/transformadores, como https://github.com/schmittjoh/JMSSerializerBundle/blob/master/Resources/doc/index.rst

Cuestiones relacionadas