2012-01-04 19 views
14

Digamos que tengo un modelo llamado John con esos parametros:Backbone.js y API REST con Silex (PHP)

{ 
    Language : { 
     code : 'gr', 
     title : 'Greek' 
    }, 
    Name : 'john' 
} 

Así que ahora cuando puedo activar John.save() que los publicara al servidor:

post params http://o7.no/ypvWNp

con esas cabeceras:

headers http://o7.no/x5DVw0

El código en Silex es muy simple:

<?php 

require_once __DIR__.'/silex.phar'; 

$app = new Silex\Application(); 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 

// definitions 
$app['debug'] = true; 

$app->post('/api/user', function (Request $request) { 
    var_dump($request->get('Name')); 

    $params = json_decode(file_get_contents('php://input')); 
    var_dump($params->Name); 
}); 

$app->run(); 

pero primero var_dump devuelto nulo segundo var_dump por supuesto funciona ya me estoy haciendo la solicitud directamente desde php://input recursos. Me pregunto cómo podría conseguir utilizando los parametros solicitud objeto de Silex

Gracias

Respuesta

15

Es bastante fácil en realidad.

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\ParameterBag; 

$app->before(function (Request $request) { 
    if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) { 
     $data = json_decode($request->getContent(), true); 
     $request->request = new ParameterBag(is_array($data) ? $data : array()); 
    } 
}); 

Y a continuación, un ejemplo de ruta:

$app->match('/', function (Request $request) { 
    return $request->get('foo'); 
}); 

Y las pruebas con curl:

$ curl http://localhost/foobarbazapp/app.php -d '{"foo": "bar"}' -H 'Content-Type: application/json' 
bar 
$ 

Alternativamente mirar el (un poco anticuado) RestServiceProvider.

EDITAR: He convertido esta respuesta en cookbook recipe in the silex documentation.

+0

Hola, muchas gracias! Esa fue una solución! Aunque creo que Silex debería cuidarlo de manera predeterminada sin la necesidad de agregar un filtro 'before'. En cuanto al tipo de contenido, '$ request-> headers-> get ('Content-Type')' devuelve 'application/json; charset = UTF-8' así que preferiría marcar de esa manera: 'if ('application/json' === strstr ($ request-> headers-> get ('Content-Type'), ';', true)) 'o para ser más a prueba de balas así:' if (false! == strpos ($ request-> headers-> get ('Content-Type'), 'application/json')) ' – panosru

+0

' 0 === strpos ('incluso, ajustaré mi respuesta. – igorw

+0

del manual php:' Esta función puede devolver un valor booleano FALSO, pero también puede devolver un valor no booleano que evalúa como FALSO, como 0 o "" .', por lo que tiendo a usar el falso en lugar de 0 :) – panosru

4

La forma en que he hecho antes es la siguiente:

$app->post('/api/todos', function (Request $request) use ($app) { 
    $data = json_decode($request->getContent()); 

    $todo = $app['paris']->getModel('Todo')->create(); 
    $todo->title = $data->title; 
    $todo->save(); 

    return new Response(json_encode($todo->as_array()), 200, array('Content-Type' => 'application/json')); 
}); 

En su colección de columna vertebral, añada lo siguiente:

window.TodoList = Backbone.Collection.extend({ 
    model: Todo, 

    url: "api/todos", 

    ... 
}); 

He escrito un tutorial completo paso a paso aquí http://cambridgesoftware.co.uk/blog/item/59-backbonejs-%20-php-with-silex-microframework-%20-mysql

0

he resuelto yo mismo mediante el establecimiento de un $payload propiedad adicional en la solicitud objeto

$app->before(function(Request $request) { 
    if (stristr($request->getContentType(), 'json')) { 
     $data    = json_decode($request->getContent()); 
     $request->payload = $data; 
    } else { 
     $request->payload = null; 
    } 
});