Manipular los datos de publicación para funcionar con formularios Symfony2 cuando se usa en una API REST

StackOverflow https://stackoverflow.com/questions/9304214

  •  25-10-2019
  •  | 
  •  

Pregunta

Fondo:

Estoy escribiendo una API RESTful en Symfony. Quiero que el cliente pueda publicar en una URL utilizando la aplicación de tipo de contenido/JSON y publique un objeto JSON de forma que la acción del controlador está buscando.

Estoy usando una configuración de controlador bastante básica para esto. Supongamos con fines de demostración que estoy tratando de autenticar un combo de contraseña de nombre de usuario simple.

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 he probado var_dumping esto hasta que las vacas lleguen a casa, es que, por cualquier razón, Symfony no quiere tomar el cuerpo de contenido de la aplicación/JSON y usar esos datos para poblar 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 que pueda hacer que esto funcione. Gracias por tu tiempo con el asunto.

¿Fue útil?

Solución 2

En realidad, he encontrado una forma similar de solucionar esto, después de verificar 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 **/
}

Otros consejos

Deberá acceder al cuerpo de solicitud sin procesar y luego usar JSON_DECODE. Probablemente necesite cambiar su bindRequest Método 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);
        }
}

Todavía no me he metido realmente con SF2, así que esto es más adivinación basada en la API, Exp. con SF1.X y cosas que he obtenido de presentaciones en el marco. También podría ser mejor hacer un método completamente diferente como bindJsonRequest Entonces las cosas están un poco más ordenadas.

Sí, lo que la forma está esperando durante la unión es una matriz que contiene claves que corresponden a las propiedades de su apiuser.

Entonces, si envía una solicitud de publicación con la cadena:

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

Tendrás que transformarlo en una matriz usando json_decode por ejemplo:

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

Luego unes esta matriz al formulario usando $form->bind($data);

El formulario actualizará sus propiedades de Apiuser correspondientes a las claves de Array (nombre de usuario, contraseña).

Si está construyendo una API JSON RESTFOR, le aconsejaría que automatice este proceso utilizando serializadores/transformadores, como https://github.com/schmittjoh/jmsserializerbundle/blob/master/resources/doc/index.rst

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top