Normalmente no soy partidario de crear un lista estúpida de propósitos de año nuevo que al final, como todos sabemos, se quedan en el aire. Pero si que me gusta tener en mente una serie de aspectos reales que debería seguir para el continuo crecimiento profesional y personal. Además, como suelen hacer esos que practican agile, creo que es muy conveniente hacer una retrospectiva para ver desde una posición objetiva cómo ha ido el año en base a lo esperaba.
Así que empiezo con la retrospectiva de 2011:
En resumen ha sido un año muy bueno, muy cargado de cosas, pero que ha supuesto un salto cualitativo importante en mi carrera profesional. Al mismo tiempo, hay cosas que tenía planeadas y no he podido cumplir. Entre ellas, la segunda parte de la certificación de MySQL o las asignaturas de la universidad que tenía para junio.
Ahora toca hacer la planificación de 2012:
Al igual que 2011, también será un año cargado de cosas, pero muy interesante y toca cogerlo con muchas ganas. ¿Qué te parece? ¿Y tú, ya has hecho tus propias retrospectivas y planificaciones?
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:
[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:
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:
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:
Hace pocos días, hablando con 2 cracks de PHP me preguntaban si conocía SPL, Standard PHP Library. En primera instancia me quedé pensando y dije que no. Pasadas un par de horas me puse a buscar información acerca de SPL y llegué a la documentación de php.net. Tras una rápida ojeada de los componentes que forman parte de esta librería me di cuenta de que indirectamente conocía esta librería y quizá a ti te pase lo mismo.
Me explico, seguro que conoces las clases DirectoryIterator, IteratorIterator, RecursiveDirectoryIterator o las interfaces Countable o RecursiveIterator. Pues bien, estas clases forman parte del componente Iterators e Interfaces de SPL.
Standard PHP Library (SPL) es una librería PHP que está compuesta por los siguientes componentes:
Esta extensión de PHP no es nueva, se incorporó parcialmente y por defecto en la versión 5.0.0 de PHP y se aumentó en 5.3, además, en esta última versión SPL no puede ser desactivada. Aun así, quizá aun sea desconocida para muchos programadores PHP.
Por mi parte voy a empaparme por completo de cómo funcionan todos los componentes y espero poder hacer uso de cada uno de ellos cuando los requerimientos me lo pidan :). Cuando estudié "Estructuras de Datos" por la facultad (con Java) vi de gran utilidad las clases que el JDK facilita para el almacenamiento masivo de datos y lo eché de menos en PHP, donde se suele hacer uso exhaustivo del array como contenedor de elementos y no siempre es lo correcto. A partir de ahora habrá que tener en cuenta más a menudo SPL y todas las posibilidades que ofrece.
La configuración de colores por defecto de Netbeans se basa en un background blanco y colores llamativos, lo cual cansa bastante la vista tras varias horas pegado al ordenador.
Cuando migré de TextMate a Netbeans lo primero que hice fue tratar de configurar los colores para que se pareciera lo máximo posible a alguno de los themes que usaba anteriormente en TextMate. Estos themes se caracterizan por usar colores oscuros para el background y colores pasteles para la codificación.
Después de cambios, ajustes y varios meses de pruebas, parece que he conseguido hacer una configuración de colores bastante agradable a la vista.
Os dejo mi theme Netbeans al estilo TextMate.
Para importar un archivo de configuración: Netbeans > Preferencias > Fonts & Colors > Import

Se permiten mejoras y modificaciones :) Espero vuesto feedback!!
Hoy en día, la mayoria de aplicaciones web hacen uso de tareas o comandos de optimización, limpieza de datos, captura de eventos, etc. Estas tareas se lanzan a nivel de sistema operativo mediante una tarea Cron (Cron jobs) que hace llamada a una dirección URL o programa.
Planteando el escenario: en uno de los últimos proyectos en los que estoy trabajando he necesitado la ejecución de una tarea para que libere la cola de envío de emails del tipo Newsletter, es decir, el usuario genera un Newsletter asociado a un listado de suscriptores y lo lanza, una vez landazo, éste queda almacenado en una cola de envío. Para liberar esta cola es necesario lanzar la tarea de Symfony project:send-emails.
Esta tarea se puede ejecutar de forma muy sencilla mediante un Cron un par de veces al día, pero ¿qué ocurre si por impedimentos del sistema no puedo depender de un sistema de Cron? No voy a entrar a explicar ahora el porqué no puedo disponer del Cron del sistema, voy a centrarme en comentar cómo lo he solventado.
Básicamente, lo que he hecho ha sido hacer uso de la función exec() de PHP pero con la peculiaridad de lanzarla en segundo plano. Esto es muy sencillo de hacer y el usuario no depende de la finalización de la tarea para que el navegador le devuelva respuesta sino que, la respuesta es inmediata y la tarea queda en ejecución de forma transparente para el usuario.
Veamos el pequeño script PHP:
<?php
$symfonyPath = sfConfig::get('sf_root_dir');
$symfonyCommand = '/symfony project:send-emails --application=backend';
$output = ' > /dev/null &';
exec($symfonyPath . $symfonyCommand . $output);
?>
Vamos a explicarlo línea a línea:
$symfonyPath = sfConfig::get('sf_root_dir');
$symfonyCommand = '/symfony project:send-emails --application=backend';
Esto no es más que la ruta donde se encuentra el ejecutable de Symfony y la llamada al task en sí, poco más..
$output = ' > /dev/null &';
Aquí está el punto más interesante. Con esta línea desviamos la salida que produce la tarea hacia una ruta que actúa como "papelera". Con esto y el caracter &, se consigue que la tarea se ejecute en background y el script PHP no requiera estar esperando la ejecución completa del task hasta tener de nuevo el control sino que, la tarea Symfony la va a gestionar directamente el SO como hilo aparte.
Por último, solo queda lanzar la tarea:
exec($symfonyPath . $symfonyCommand . $output);
De esta forma he conseguido vaciar la cola de envío de emails sin necesidad de una ejecución por medio de Cron y además tengo el control de cuando hacerlo. De esta forma, tras el click del usuario en "Enviar Newsletter" no solo se almacena la cola de envío sino que acto seguido el sistema empieza a procesarla y la gracia de todo esto es que todo queda transparente para el usuario que ejecuta la acción.