Ya que ayer hablaba de crear un web service con SOAP hoy toca complementar la información creando un web service REST. Esto nos permitirá crear lo que podríamos llamar una RESTful API.
En este caso nos vamos a servir del framework Slim y de la librería NotORM para el acceso a la base de datos.
Lo primero que haremos será crear una suerte de Hello World con Slim, para probar su funcionamiento
<?php require "Slim/Slim.php"; // creamos una nueva instancia de Slim $ejemplo = new Slim(); // agregamos una nueva ruta y un código $ejemplo->get("/", function () { echo "<h1>Ejemplo</h1>"; }); // corremos la aplicación $ejemplo->run();
Vale, ejemplo simplón de cómo usar Slim, más adelante veremos algo más. Ahora vamos con la conexión a la base de datos, en la que usaremos NotORM y PDO:
<?php require "NotORM.php"; $pdo = new PDO($dsn, $username, $password); $db = new NotORM($pdo);
Ok, conexión creada. Vamos a suponer que tenemos una base de datos con nombres de discos. La idea sería crear un webservice que nos devolviera todos los discos de la base de datos, codificados como un objeto JSON:
<?php $app = new Slim( "MODE" => "developement", "TEMPLATES.PATH' => "./templates" ); $app->get("/discs", function () use ($app, $db) { $discs = array(); foreach ($db->discs() as $disc) { $discs[] = array( "id" => $disc["id"], "title" => $disc["title"], "band" => $disc["band"], "genre" => $disc["genre"] ); } $app->response()->header("Content-Type", "application/json"); echo json_encode($discs); });
Bueno, primero creamos una instancia de Slim, definiendo que la utilizaremos en un entorno de desarrollo y apuntando en qué carpeta están las plantillas de la maquetación. Verás que en el ejemplo hemos llamado al método get(), es uno de los métodos de Slim que te enruta a una petición GET en la url que se le envía como primer argumento. Como segundo argumento le enviamos una función callback que se ejecutará como respuesta. La palabra use nos permite acceder a las variables externas desde dentro del ámbito de aplicación de la función anónima.
Ahora un ejemplo donde se haría lo mismo pero pidiendo los datos de un disco concreto:
<?php $app->get("/disc/:id", function ($id) use ($app, $db) { $app->response()->header("Content-Type", "application/json"); $disc = $db->discs()->where("id", $id); if ($data = $disc->fetch()) { echo json_encode(array( "id" => $data["id"], "title" => $data["title"], "band" => $data["band"], "genre" => $data["genre"] )); } else{ echo json_encode(array( "status" => false, "message" => "No existe un disco con el id $id " )); } });
A diferencia del anterior ves que en la ruta ahora enviamos la id del disco a buscar como parámetro.
Ok, esto nos permite insertar datos, pero ¿para insertar y modificar? Bueno, vamos a hacer un método para insertar los datos (mediante el método post() de Slim) y otro para actualizarlos (el método put()):
<?php $app->post("/disc", function () use($app, $db) { $app->response()->header("Content-Type", "application/json"); $disc = $app->request()->post(); $result = $db->discs->insert($disc); echo json_encode(array("id" => $result["id"])); }); $app->put("/disc/:id", function ($id) use ($app, $db) { $app->response()->header("Content-Type", "application/json"); $book = $db->discs()->where("id", $id); if ($disc->fetch()) { $put = $app->request()->put(); $result = $disc->update($put); echo json_encode(array( "status" => (bool)$result, "message" => "El disco $id ha sido actualizado" )); } else{ echo json_encode(array( "status" => false, "message" => "El disco $id no existe" )); } });
El primer método nos devuelve el id del último disco insertado, el segundo nos devuelve un valor verdadero o falso y un mensaje de error u éxito. Supongamos que quisieras acceder a esto por medio de un formulario (aunque lo normal en una de estas API es hacerlo mediante el envío de datos por la URL). ¿Cómo diferenciarías si es una nueva inserción o una edición? Fácil, crea un campo oculto llamado _METHOD y dale el valor PUT, tal cual como en el ejemplo:
</pre> <form class="hiddenSpellError">action="#" method="post"></form> <pre> <input class="hiddenSpellError" type="text" />type="hidden" name="_METHOD" value="PUT"></pre> Title: <input class="hiddenSpellError" type="text" />type="text" name="title"> <pre></pre> Band: <input class="hiddenSpellError" type="text" />type="text" name="band"> <pre></pre> Genre: <input class="hiddenSpellError" type="text" />type="text" name="genre"> <pre> <input class="hiddenSpellError" type="text" />type="submit" value="Submit"> </form>
Ok. Nos queda el borrar datos para tener todas las operaciones CRUD en nuestra RESTful API. Ahora nos serviremos del método delete() de Slim.
<?php $app->delete("/disc/:id", function ($id) use($app, $db) { $app->response()->header("Content-Type", "application/json"); $disc = $db->discs()->where("id", $id); if ($disc->fetch()) { $result = $disc->delete(); echo json_encode(array( "status" => true, "message" => "Disco borrado exitosamente" )); } else{ echo json_encode(array( "status" => false, "message" => "El disco con id $id no existe" )); } });
El framework Slim provee de muchas posiblidades a la hora de crear servicios web. Esto es una explicación básica de cómo se crearía cada método, pero las posibilidades son muy grandes. En su página de documentación puedes estudiar cómo sacar el 100% a este framework.
Esto está excelente, muy buena explicación, es genial esto de utilizar más el backend para solo generar JSON, y hacer esos trámites, y usar mucho más frontend para los sitios y utilizar toda la info que recibimos mediante JSON.
Excelente explicación, la pondre en practica mas tarde gracias por el aporte
Saludos.
Seria ideal contar con un ejemplo para descargar
Lo que veo que no has puesto es la consulta a la DB… ¿o me he perdido algo?
se supone que va dentro de la función anónima antes de crear el array (ejemplo get). Cierto?
Vale, perdón. No había visto lo de NotORM… Lo veo un poco armada sobre todo para las consultas complejas que tengo en mi proyecto. Supongo que el que está acostumbrado le irá genial sobre todo por la seguridad contra el SQL injection…
Sería ideal contar con un ejemplo para descargar.