Slim Framework

Introducción a Slim, un framework php-rest

Louis Anquetin

archivado en: PHP/AJAX / 8 febrero, 2015

OJO: este tutorial sirve para la versión 2 del frame y alguna cosa ha cambiado en las nuevas versiones del frame, como la instalación mediante composer

Slim es un microframework para desarrollar el lado del servidor de una api rest con php. Es muy ligero, está bien documentado y, sin duda, una opción muy recomendable cuando el peso de nuestra aplicación recae del lado del cliente, por ejemplo cuando usamos angular, ember, backbone o cualquier otro frame mvc de javaScript.

Dicho de otra manera, funciona muy bien cuando solo necesitamos php para lanzar las operaciones rest contra la base de datos que nos solicita una aplicación en cliente. En caso de que necesitemos un tinglado más complejo, creo que es mejor usar simfony o codeigniter o cualquier otro frame php más pesado, pero vamos, para trabajar con angular es perfecto.

La instalación manual es muy sencilla: descargas el zip y lo extraes en un directorio (admin, rest... cómo sea que te apetezca llamarlo). Lo que nos interesa es el archivo index.php y lo que hay en la carpeta Slim. Lo demás es accesorio.

Hola Mundo

Para estructurar la aplicación recomiendo seguir los consejos de Israel Parra, aka Uno de Piera, que permite un desarrollo escalable y ordenado.

En index.php preparamos algo así:

<?php

/* Cargamos Slim y lo instanciamos */

require_once('Slim/Slim.php');

\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim();

/* Esta constante obliga a entrar sí o sí por index.php, como veremos luego */

define("MAIN_ACCESS", true);

/* Cargamos los archivos que vayamos a necesitar, cuanto menos la conexión y los métodos principales, pero podemos crearnos un utils.php o lo que sea... */

require_once('lib/connect.php');

require_once('app/main.php');

/* Ponemos en marcha el tinglado*/

$app->run();

Así en lib, de librerías, podemos poner la conexión, en este caso pdo (vd infra):

<?php

if ( !defined("MAIN_ACCESS") ) {

header('HTTP/1.1 403 Forbiden');

echo "You shall not pass!";

die();

}

function getConnection() {

try {

$db_host = "localhost";

$db_database = "quiron";

$db_username = "root";

$db_password = "";

$connection = new PDO("mysql:host=".$db_host."; dbname=".$db_database."", $db_username, $db_password);

$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

} catch (PDOException $error) {

header('HTTP/1.1 501 Internal Server Error');

$msgError = array();

$msgError['status'] = "error";
$msgError['type'] = "database conexion";

$msgError['longDesc'] = $error->getMessage();

echo json_encode($msgError);

die();

}

return $connection;

}

...Y los métodos rest en main.php (o similar).

<?php

if ( !defined("MAIN_ACCESS") ) {

header('HTTP/1.1 403 Forbiden');

echo "You shall not pass!";

die();

}

$app->get("/foo/", function() use($app) {

echo "Hola Mundo";

});

Ale op, si ahora vamos a nuestra_ruta_de_pruebas/foo, como las peticiones de ese tipo son get, en pantalla nos debería aparecer un formidable Hola Mundo; pero hacer también la prueba de intentar entrar en main.php o la conexión, gracias al truco de Israel, la aplicación se detiene y lanza un sonoro You shall not pass!, capaz de detener al Balrog más malintencionado.

Nueve anillos

Slim está pensado para gestionar la comunicación http entre el server y el cliente, por lo que da un poco igual qué interfaz usemos para trabajar con la base de datos: mysqli, pdo, mongo...

Se escapa de la intención de esta entrada analizar cuál es la más conveniente, un tema muy tratado en la red y de complicada respuesta. Mi consejo -y no soy un experto ni de lejos en bbdd- es que tiremos de myqli, que es más rápida, cuando estemos seguros de que no vamos a migrar de base de datos, por ejemplo, cuando estemos preparando una api para un cliente que ya tiene una montonera de cosas trabajadas en mysql.

Sin embargo, cuando no tenemos muy claro quién usará nuestra aplicación, como me ocurre ahora con un cms que estoy preparando para montar un fotoblog, es más interesante utilizar pdo, pues, como es sabido, consiste en una capa de abstracción para acceder a los datos, por lo que será más fácil para quien lo necesite adaptarla a sus necesidades.

En cualquier caso, en esta explicación usaré pdo para los ejemplos.

Como ya sabemos, en una api rest, los recursos se localizan a partir de su url y la acción que se debe realizar en cada caso depende del verbo rest que se especifique en el request del cliente. Es decir, que no tendríamos un método de este tipo para coger los nueve anillos que Saurón dio a los hombres:

public function getAnillos() {

// select from La forja del destino...

}

y este otro para eliminarlos:

public function deleteAnillos() {

// delete from La forja del destino...

}

Por el contrario, tendríamos solo una url -anillos-, contra la que realizar operaciones crud (create, read, update, delete) especificadas con un verbo rest. Pues bien, lo chulo de Slim es que a partir de este verbo, ya lanza el método que le corresponda:

$app->get("/anillos/", function() use($app) {

// consultas get

});

$app->put("/anillos/", function() use($app) {

// consultas get

});

$app->delete("/anillos/", function() use($app) {

// consultas get

});

...

Una primera consulta

Sin entrar en honduras de PDO, que necesitaría una entrada aparte, un método estándar podría tener una estructura similar a esta, donde jugamos con try / catch para devolver un 200 o un 500 en función del éxito o el fracaso de la consulta.

$app->get("/libros/", function() use($app) {

try {

/* Cargamos la conexión */

$connection = getConnection();

/* Preparamos la consulta */

$dbh = $connection->prepare("SELECT `titulo`, `autor` FROM libros");

/* La ejecutamos */

$dbh->execute();

/* La almacenamos en un array con fetch, fetchAll o similar */

$result = $dbh->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP);

/* Definimos los headers */

$app->response->headers->set("Content-type", "application/json");

$app->response->status(200);

/* Enviamos la respuesta (response), en este caso como un jasonako */

$app->response->body(json_encode($response));

} catch(PDOException $e) {

/* Si el server ha cascao, avisamos... */

$error['error'] = $e->getMessage();

/* Con halt devolvemos un código y un mensaje de forma automática */

$app->halt( 500, json_encode($error['error']) );

}

});

Tenemos dos maneras principales para recoger parámetros, una es cuando vienen en la url, y es muy similar a cualquier recepción de parámetros en php.

foo/33

$app->get("/foo/:id", function($id="valor por defecto") use($app) {

echo $id; // 33

});

Y si vienen a modo de query string, con el método request->params

/rest/foo?id=33

$app->get("/foo/", function() use($app) {

$id = $app->request->params('id');

echo $id; // 33

});

Y la segunda es cuando vienen en el cuerpo (body) del request, como suele ocurrir con las peticiones ajax.

/* Si estamos hablando en jasonako... */

if ( $request->getMediaType() == 'application/json') {

/* Cacheamos el body */

$post = $request->getBody();

/* Lo decodificamos... */
$post = json_decode($post, true);

...

Bueno, quedan muchas cosas que explicar, como la manear de cachear respuestas, pero las dejo para otro día, que como introducción ya está bien : )

|| Tags: , ,

valoración de los lectores sobre Slim Framework

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 4.5 sobre 5 (2 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

4 respuestas a “Slim Framework

  1. muy interesante, escueto y sencillo, pero sobre todo muy claro…..
    Ojalá saques pronto lo que dices que falta por detallar, caches, etc..
    Felicidadessssss y espero tu próxima entrega

  2. marcos el dijo:

    Hola Marc, gracias.

    Buf, pues lo cierto es que tengo una montonera de post pendientes, como las series de mongo y node.

    No creo que antes de septiembre siga con esto, sorry.