aramirez.es

Alberto Ramírez Website


25 de julio de 2011

Silex desde un ejemplo real

4 comentarios >>

Tras asistir al evento Desymfony en Castellón a principios de julio, llegué a casa con pilas cargadas para aprender tecnologías que allí se habían mostrado. Quedé encantado con Silex, Git, jQuery Mobile, cómo no con Symfony2, etc. Lástima que uno siempre anda mal de tiempo como para ponerse a aprender tanta cosa, así que me vino a la cabeza el hecho de crear una aplicación pequeña (donde Silex vendría de maravilla), ubicarla en Github (Así podría  aprender lo básico de Git) y haciendo uso de HTML5. Con esto mataba varios pájaros de un tiro. 

En este post, básicamente voy a hablar de Silex, que para quien no lo conozca se trata de un micro framework creado en PHP y basado en Symfony2 (silex-project.org), del que @nacmartin nos dio una maravillosa charla con la que creo que todos quedamos encantados.

[Requerimientos en instalación]

Al igual que Symfony2, Silex corre a partir de la versión 5.3 de PHP y ciertas extensiones pueden tener requerimiento de librerías que por defecto no vienen compiladas en el core de PHP. Un ejemplo de esto es la extensión Session, que hasta hace poco requería de la clase Locale de la librería Intl y digo hasta hace poco porque esta dependencia se hizo opcional y ahora, previamente a invocar la clase Locale, se mira si ésta existe o no.

La instalación es sencilla y se puede hacer de varias formas: bien vía git mediante su repositorio en https://github.com/fabpot/silex (que requerirá de una posterior compilación) o bien descargando el fichero ya compilado en formato phar. Yo particularmente me descargué el phar y lo he ido actualizando mediante consola con el simple compando php silex.phar update. Con esto, la instalación está terminada.

[Funcionamiento, servicios y extensiones]

Siguiendo con la sencillez característica de Silex, para declarar éste y hacerlo funcionar solo es necesario cargarlo desde un fichero php e instanciarlo de esta forma:

require_once __DIR__.'/silex.phar';
$app = new Silex\Application();
// Your code here.
$app->run();

Sin entrar en detalles de cómo funciona Silex y todo lo que se puede hacer con este micro framework (que para eso está su fantástica documentación), voy a mostrar las extensiones que yo he necesitado y los servicios que me he creado. Antes de nada, ¿qué es una extensión? ¿Qué es un servicio? ¿Y cuál es la diferencia entre ambos?

Un servicio en Silex es un recurso de tipos variables, objetos, etc. Que gracias al contenedor de servicios de Silex, siempre estará disponible. Ejemplo:

$app[‘my_service.host’] = ‘172.0.0.1’;
$app[‘my_service.connection’] = function() use ( $app )
{
    return new \MyConnectionClass( $app[‘my_service.host’] );
}
// Usage.
$app['my_service.connection']->connect();

En este ejemplo podemos ver cómo se hace uso de dos características inexistentes en PHP hasta la versión 5.3: funciones anónimas y clousures, de ahí que Silex requiera esta versión de PHP como mínimo.

Una extensión se puede ver como una librería externa que puede ser registrada y usada por Silex. Ya hay algunas extensiones que están preparadas para ser cargadas, como son DoctrineExtension, SessionExtension o TwigExtension. Creo que con estas tres ya cubrimos gran parte de las necesidades que una aplicación de tamaño pequeño puede tener.

$app->register(new MyLibrary\SomeExtension(), array(
    'config.host' => '127.0.0.1',
));

En este código, obviamente no se aprecian diferencias notables, pero mi intención no es la de documentar Silex (qué ya lo está y de forma increíble) sino la de comentar mi primera toma de contacto con el micro framework. Lógicamente, existen diferencias entre servicios y extensiones y voy a comentar de forma rápida cómo las veo yo:

  • un servicio es una utilidad disponible en cualquier momento que puede ser desde un array asociativo hasta un objeto que realice determinadas acciones, la forma de declararlo es sencilla y no implica mucha dificultad.
  • Una extensión, por el contrario podría ser una librería externa e independiente que  consta de múltiples clases, interfaces y sistemas propios y que ha de ser adaptada a Silex. Para ello, la clase encargada de adaptar esta librería al framework debe cumplir ciertas reglas, como por ejemplo extender de Silex\ExtensionInterface e implementar el método register. Además en la documentación, hablan de ciertas buenas prácticas a la hora de crear tus extensiones.

[Aplicación Real]

Muy bien, hasta aquí todo muy bonito, pero ¿Cómo es una aplicación real? Voy a contar qué estoy haciendo en mi caso: como eran varias tecnologías las que iba a probar a la vez ¿por qué no añadir alguna más? ¿Por qué no hacer pruebas con alguna API y sistemas REST como el de Twitter? Pues si, estaría bien :) Manos a la obra.

Si se trata de una aplicación que va a usar la API de Twitter, requeriré de algún sistema de persistencia para el Singin, nada mejor que usar la extensión SessionExtension para empezar. Además, qué menos que usar un sistema de plantilla ¿no? Twig! Ya hay para empezar a divertirme.

require_once ( __DIR__ . '/silex.phar' );
require_once ( __DIR__ . '/vendor/twig/lib/lib/Twig/Autoloader.php' );
Twig_Autoloader::register();
$app = new Silex\Application();
$app->register( new Silex\Extension\SessionExtension() );
$app->register( new Silex\Extension\TwigExtension(), array(
    'twig.path' => ( __DIR__ . '/views' ),
    'twig.class_path' => ( __DIR__ . '/vendor/twig/lib' )
));

Aquí se puede ver como SessionExtension no se carga previamente, a diferencia de Twig que ha de ser descargado, incluido y además require hacer una llamada al register del autoloader. Esto es debido a que Silex se compila con Session pero no con Twig. Es algo que eché de menos en la documentación de Silex.

Lo siguiente es ver que para realizar las peticiones hacia la api de Twitter voy a necesitar tres escenarios distintos como mínimo:

  • Home page: solicita Sign in y provee la funcionalidad del proyecto tras hacer login.
  • Sign in: hará las comprobaciones pertinentes y redireccionará a Twitter.
  • Callback: un sitio donde Twitter confirme el login y redireccione al Home de nuevo.

Por lo cual, ya podemos crear la primera versión del routing

$app->get( '/', function() use ( $app ) {} );
$app->get( '/twitter-signin', function() use ( $app ) {} );
$app->get( '/receive-response-twitter', function() use ( $app ) {} );

Lo último que queda es usar alguna librería OAuth adaptada a Twitter, pero además habría que encapsularlo con un adapter que se sitúe entre mi aplicación y la librería OAuth. Qué mejor que crear un servicio de Silex que contenga este adapter y así probar cómo funcionan los servicios también.

require_once ( __DIR__ . '/vendor/adapter/twitter/lib/TwitterAuthAdapter.class.php' );
$app['twitter.customer_key']    = 'fakecustomerkey';
$app['twitter.user_password']   = 'fakepassword';
$app['twitter.callback_url']    = 'fakecallback';
$app['twitter'] = $app->share( function() use ( $app )
{
    return new Twitter\TwitterAuthAdapter ( $app['twitter.customer_key'], $app['twitter.user_password'] );
});

Además del adapter habrá que crear el modelo que se encargue de ejecutar la lógica de negocio (por poco que sea) de la que consta esta aplicación y por último crear el routing para las acciones, que en mi caso son dos.

[Resumiendo]

Hasta ahora tengo: 

  • index.php con la declaración y registro de silex, servicios y extensiones, 5 routings diferentes y lógica de aplicación. 
  • Luego, por otro lado tengo la vista con Twig.
  • Y l lógica de modelo por otro.

Mmmmm, empiezo a ver algo… ¿Estoy intentando emular un MVC? Parece que sí y ha sido de forma inconsciente, simplemente aplicando la organización que desde hace años he estado usando. Aparte, el index.php empieza a crecer de una forma considerable ya que contiene toda la inicialización de Silex, sus extensiones, mis servicios pero además, el enrutamiento y toda la lógica de aplicación. Creo que he llegado a un punto, me estoy contestando a esa pregunta que siempre tenemos presente y que hicieron en la charla de @nacmartin, ¿Cuándo debemos usar un micro-framework y cuándo un framework?

Pues mi opinión al respecto, es la siguiente: cuando las necesidades de tu aplicación no crecen más allá de un par de plantillas que requieren algo de dinamismo, o bien se necesita procesar y almacenar (o enviar por email) los datos de un formulario o proveer de algún tipo de servicio web (REST o xml), tu herramienta es un micro-framework, tu herramienta es Silex.

Si necesitas más lógica (tanto de aplicación como de negocio), si necesitas crear una estructura organizativa porque tienes un número de ficheros considerables, si necesitas ceñirte al patrón MVC, si tu index.php empieza a ser poco mantenible, necesitas un framework, pero si tu aplicación es demasiado grande para ser creada con Silex pero no lo suficiente para usar Symfony2, prueba otras opciones, existen frameworks MVC en PHP más livianos que Symfony2 y se podrían ajustar seguramente mejor a tus necesidades.

Como digo, es mi opinión :-)

Para acabar, comentar que, para cumplir con su cometido, Silex está muy bien pensado, muy bien hecho y es una gozada usarlo, lo recomiendo totalmente. Siempre y cuando tu aplicación no exceda en cuanto a complejidad ;-)

En breve haré público el repositorio con la aplicación que estoy haciendo para probar Silex, además, tengo pensado ponerla en producción también.

 

[Actualización]

Os dejo el enlace con el repo en Github: https://github.com/aramirez-es/Compare-follows

[Actualización 23 agosto]

La web está en producción en el siguiente dominio: http://www.comparefollows.com

 

Enlaces interesantes:

 

Tags: | |


Comentarios

  • Nacho
  • #1 Nacho (25/07/2011 14:14)
  • Ah! qué bien que te haya gustado Silex :)

    Me parece acertado lo que dices de cuando el proyecto empieza a crecer y cuándo escoger Silex. Respecto a eso, puede ser útil esta presentación:
    http://www.slideshare.net/IgorWiedler/silex-the-symfony2-microframework

    , a partir de la transparencia 37 muestran algunas recetas para organizar el código, tener un fichero de configuración yml, etc. que parecen buenas ideas para mantener el orden cuando el proyecto empieza a crecer un poco sin que haya que abandonar aún Silex.

    Ah, y muchas gracias!
  • Alberto
  • #2 Alberto (25/07/2011 15:27)
  • Gracias por tu feedback, Nacho :-)

    Me apunto la presentación para verla tranquilamente porque me puede ser útil tal y como tengo el proyecto ahora.
  • cordoval
  • #3 cordoval (25/07/2011 19:41)
  • wow production man! you got it, keep me posted man
  • Juan Antonio
  • #4 Juan Antonio (23/08/2011 15:45)
  • Increíble tutorial!!! Buscaré tiempo para adentrarme en Silex. ^^
Deja tu comentario

zukeidigital 2008