En el momento en el que uno comienza a pensar en el diseño técnico que necesita para desarrollar el back-end de una aplicación web de complejidad media/alta, enseguida se da cuenta que intentar abarcarlo todo con código PHP nativo no es práctico. Tareas como gestionar las plantillas de front-end, acceso a base de datos, gestión de formularios, validaciones, variables de sesión, etc … tienen una implementación un tanto costosa en PHP nativo, y en muchos casos obligan a casarse con determinadas herramientas, cuando fácilmente podría abstraerse de ellas (como puede ser la elección del gestor de base de datos).

Uno puede verse tentado a desarrollar sus propias librerías (“esto me lo hago yo en un periquete“). Personalmente pienso que eso es un gran error. Esa filosofía está bien mientras uno está estudiando y formándose, para entender mejor como funcionan las cosas por dentro, pero en cuanto estamos en el mercado laboral y tenemos que ofrecer a nuestros clientes productos de calidad en un plazo de tiempo razonable, pensar que nosotros solos, por nuestra cuenta, somos capaces de desarrollar todas estas librerías, con una calidad similar que las comunidades de desarrolladores experimentados, suena un tanto pretencioso, ¿no crees? :-). (1)

¡¡ No reinventes la rueda !!. En el 99.99% de los casos, el mismo problema que tienes ahora encima de la mesa, lo han tenido miles de personas antes, y te explican como resolverlo correctamente.

Es aquí donde aparecen los frameworks, para facilitarnos la vida poniendo a disposición del desarrollador un conjunto estandarizado de conceptos, buenas prácticas, criterios, y librerías, que le ayuden a preocuparse por el negocio de su cliente, y no por decidir donde ubicar una librería, o como hay que hacer para guardar un registro en la base de datos. (Di NO al código espagueti).

Hay donde elegir

Existen bastante competencia entre la que elegir, cada uno con sus ventajas e inconvenientes. Entre los mas relevantes, podemos encontrar: Symfony, Zend framework, Laravel, CakePHP, Yii, Phalcon, CodeIgniter.

También existen los micro-frameworks, versiones sencillas y ligeras de fácil instalación. Symfony tiene un hermano pequeño llamado Silex.

¿Con cual me quedo?
Pues no se puede decir que haya un ganador absoluto. Aunque tienen muchos puntos en común, cada uno implementa una aproximación diferente para solucionar problemas similares, unos mejor que otros. Influye mucho el proyecto en el que va a ser aplicado: volumen de tráfico previsto, necesidades de integración con herramientas que ya tenga el cliente, etc.

Durante la toma de requisitos, evalúa si lo que te pide el cliente se puede resolver con alguna herramienta que ya exista en el mercado, lo que te ahorrará tiempo y costes. Si simplemente quiere una página sencilla para tener presencia online y/o un blog, lo resuelves con un WordPress, si quiere una tienda online, mejor configúrale un PrestaShop, Magento, o un Shopify, si quiere un foro mira phpBB o similar, si quiere algo más complejo aún puede encajar en las funcionalidades de algún CMS como Drupal o similar.

En mi caso particular, pensando en que el tipo de aplicaciones que vamos abordar son de complejidad media y alta, veo que Symfony es la herramienta adecuada. Quiero compartir con vosotros el análisis que me ha llevado a esta conclusión.

Los pilares

El core de Symfony se basa en la integración de 4 productos muy potentes ya existentes en el mercado, que podríamos haber instalado de forma individual en nuestra aplicación:

Un motor de plantillas “rápido, seguro y flexible“, también propiedad de SensioLabs. Resuelve a la perfección la separación de la renderización de las vistas del patrón MVC. Permite herencia de plantillas, de forma que defines un layout general, y bloques de código html, similares a widgets, que son embebidos en cualquier parte del layout. Es extensible mediante el sistema de Bundles de Symfony, de forma que se pueden añadir nuevas funcionalidades muy fácilmente, como ejemplo, la manipulación de imágenes y generación de thumbnails con LiipImagineBundle, entre otros, o gestionar la personalización temas mediante LiipThemeBundle.

Un ORM (mapeador de objetos-relacional) que nos facilitará mucho la vida a la hora de trabajar con la capa de persistencia en base de datos (después de pillarle el truco a los archivos de definición de las entidades y las relaciones entre ellas, que no es inmediato), de mostrar/renderizar la información de una entidad y sus relacionadas en una página html, de transformarla en estructuras JSON o XML, de abstraernos el motor de base de datos a utilizar, de balancear entre las máquinas de un cluster de servidores maestros / esclavos según estemos actualizando o solo consultando, con drivers para conectaros a los motores más habituales (MySQL, PostgreSQL, Oracle, MS-SQL Server, SQL Lite, SAP Sybase SQL), y también a NoSQL como MongoDB.

Librería para el envío de correos electrónicos. Permite usar SMTP, sendmail, Postfix o un transporter personalizado, como por ejemplo GMail, de forma sencilla, soporta servidores que necesitan autentificación, fácil integración para envío de contenido HTML y texto plano alternativo, adjuntos, sistema de encolado de emails, con plugins para controlar libreración gradual de los correos, registro de la traza de toda la comunicación con el servidor SMTP saliente, y más.

Librería para registro de la actividad de una aplicación en ficheros de log, que implementa el estandar PSR-3. Define 9 niveles de criticidad de un mensaje (log, debug, info, notice, warning, error, critical, alert, emergency), permite registrarlas en archivos de disco, base de datos, notificación por correo electrónico, definición de diferentes canales de logueo, y más. Por ejemplo, permite definir un canal por el cual, si la aplicación registra un mensaje de nivel error o superior, que lo guarde en un archivo de disco, y envíe un correo electrónico al equipo de soporte.

Ampliable

Este es uno de los puntos fuertes. En los pilares de la estructura de Symfony se encuentra la de organizar las funcionalidades en paquetes, o Bundles (en su propia terminología). ¿Necesitas algo que no viene en el core?. Lo más probable es que alguien haya tenido antes la misma necesidad, así que antes de ponerte a desarrollarlo por tu cuenta, consulta si existe algún Bundle que puedas instalar en tu aplicación que lo resuelva. (Mejor será invertir media mañana y encontrar un Bundle de calidad que resuelve correctamente el problema, que no gastar días de trabajo en hacer algo ad-hoc).

Hay centenares de Bundles disponibles. Esta es una lista de los 30 Bundles más interesantes y usados, según el propio SensioLabs, o esta lista de bundles populares, según Symfony.es.

A modo de introducción, nos podemos encontrar:
FOSUserBundle, para resolver el problema de alta de usuarios, confirmación de la dirección de email, gestión de olvidos de contraseña, etc.
HWIOAuthBundle Para habilitar que los usuarios se registren en tu plataforma con sus cuentas de Facebook, Twitter, Google+, y muchas mas (aquellas que permitan la autentificación mediante OAuth).
FOSRestBundle para habilitar fácil y rápidamente un API Rest.
JMSSerializerBundle para transformar tus entidades a estructuras JSON, XML y/o YAML.
LiipImagineBundle para el tratamiento de imágenes (crear miniaturas/thumbnails, añadir marcas de agua, recortar, rotar, etc).
StofDoctrineExtensionsBundle añade funcionalidades extra a las entidades que almacenaremos en base de datos, como son definir listas ordenables (sortable), listas en árbol (tree), atributos que hacen referencia a un archivo subido por el usuario (uploadeable), atributos que registren automaticamente la fecha y hora de guardado, atributos de texto que pueden tener traducción en varios idiomas, y más.
JMSSecurityExtraBundle añade funcionalidades y facilita la gestión de permisos de acceso a los diferentes recursos y urls de nuestro sitio, de forma rápida, sin necesidad de tener que activar el pesado ACL o los Voters.

En ocasiones, te puedes encontrar un Bundle que si resuelve el problema que tienes, pero no de la forma que te habías imaginado. En este momento deberías preguntarte: ¿Me puedo adaptar yo (y mi aplicación) a como resuelve este bundle mi problema?. En la mayoría de los casos, la respuesta debería ser SI, y ser tú quien te adaptes. De esta forma, te estarás alineando con las buenas prácticas que llevan implícitos los Bundles de calidad, aprovecharás las actualizaciones y mejoras que aporte la comunidad que lo soporta, facilitarás el trabajo futuro de mantenimiento, para ti y/o para el equipo encargado. Por norma, suele haber mas ventajas que inconvenientes.

Buenas prácticas

Symfony sigue un conjunto de buenas prácticas determinadas por la comunidad para el desarrollo de software, como son:

Programación orientada a objetos (OOP)
Modelo Vista Controlador (MVC)
Inyección de dependencias (DI)
Mapeador de objetos relacional (ORM)
Internacionalización (i18n)
Coding Standars
– Helpers
REST
JSON-RPC
Scaffolding
Configuración mediante archivos YAML
Annotations
Mecanismo de caché
Autentificación y Autorización
– Sistemas de seguridad para evitar ataques por fuerza bruta, CSRF, SQL Injection, etc.
Integración con pruebas unitarias (TDD) y de comportamiento (BDD)

Documentación, aprendizaje y comunidad

La curva de aprendizaje en Symfony no es trivial, más exigente que en otros frameworks mas livianos, pero comparada con Zend, sin duda es menos dolorosa. La documentación de Zend parece estar orientada para los desarrolladores del framework, no para personas no iniciadas. En su lugar, Symfony publica una documentación bastante completa, con un Cookbook que provee de ejemplos bastante claros de como utilizar las principales características (aunque a veces solo detalla el caso de uso más relevante según su criterio, y omite explicar para que sirven otros parámetros o valores, lo que obliga a investigar por la red).

A día de hoy, Google nos dice que Symfony es el más popular entre ellos. Esto dice algo muy positivo, y es que hay una amplia comunidad de gente activa interesándose y colaborando con este framework. En stackoverflow.com podemos encontrar mucha ayuda, y respuestas a preguntas frecuentes.

Con las manos en la masa

Al ser tan popular, los IDE más utilizados se han preparado para mejorar la integración y la experiencia de desarrollo, reconociendo code completion, coding style, atajos para acceder a la definición de métodos, clases, ficheros de configuración, etc., como es el caso de los plugins para Netbeans, Eclipse, Sublime, o el prestigioso (y de pago) phpStorm.

En el entorno de desarrollo, incluye automáticamente en el pie de cada página una Debug toolbar and Profiler de gran utilidad, pudiendo acceder desde ahí a mucha información relevante para el desarrollador. (Basta ya de tanto print_r y var_dump).

Mediante la Consola de comandos podremos ejecutar proceso batch, tanto desarrollados por nosotros, como funcionalidades propias de Symfony.

Integración con otras herramientas

Existen Bundles para conectar con herramientas de terceros, como:
phpDocumentator
Memcached o Redis
PHPUnit y Behat
Capistrano

… entre muchas.

Casos de éxito

Como me decía un antiguo jefe: “los experimentos en casa, y con gaseosa“. Con esto nos quería transmitir que para su negocio necesitaba herramientas contrastadas en las que pudiera confiar. En este sentido, tanto Zend Framework como Symfony destacan por su grado de madurez.

Entre los proyectos de envergadura que funcionan con Symfony podemos encontrar a TED, Dailymotion, Yahoo! Answers, Yahoo! Bookmarks, delicious.com, eZ Publish o Drupal (desde su versión 8).

El equipo de Octivi nos detalla el caso de éxito de esta aplicación que responde 1,000 millones de peticiones por semana con un tiempo medio de respuesta de 30 milisegundos. A través de High Scalability sabemos que lo han conseguido con tres servidores de la aplicación front (HAProxy, PHP-FPM, Varnish), dos servidores MySQL master (+1 backup) y dos servidores Redis.

Desde el propio Symfony nos describen como fue la implementación del proyecto Dailymotion.

Contras

No todo es de color de rosa. La curva de aprendizaje no es trivial. Deberás estar familiarizado con patrones y conceptos como Programación orientada a objetos (OOP), Modelo Vista Controlador (MVC), Inyección de dependencias (DI), Mapeador de objetos relacional (ORM), herramientas como Composer.

Trabajar con Doctine como ORM es muy productivo (desde el punto de vista del desarrollador). El poder acceder a las entidades hijas/padre de cualquier entidad y que se carguen solo cuando se accede a ellas, que se actualicen o borren en cascada, sin escribir nada de código (solo configurando los archivos .orm) es una maravilla, pero para llegar a tenerlo funcionando correctamente, antes tendrás que pelearte un poco para pillarle el truco a como se definen las relaciones 1 a N, y N a M (donde utilizar mappedBy e inversedBy. Recomiendo tener a mano esta ORM Cheatsheet). Además, si el modelo de base de datos ya lo tienes definido antes de empezar, te puedes encontrar con que a Doctrine no le gusta como se han creado las claves primarias, o las relaciones entre entidades, y obligarte a hacer cambios en el modelo.

En el entorno de producción exige que tengas instalado APC, OPCache, o algún otro acelerador de código PHP. Esto es bueno para tu aplicación. Te está obligando a tener una máquina donde va a rodar rápido, pero por contra, la instalación se hace más compleja, y necesitas tener cierto control sobre el Hosting donde la vayas a hospedar, así que tenlo en cuenta antes de contratar uno.

Si prevés que vas a tener un tráfico elevado, lo mejor será que tengas presente desde el principio el cacheado en memoria de las variables de sesión, consultas frecuentes a base de datos con baja variabilidad, renderizado de páginas enteras, etc. La integración de Symfony con Memcached y Redis es buena, pero como antes, necesitas que tu Hosting lo tenga disponible.

Conclusión

Symfony2 tiene todo lo necesario para poder abordar el desarrollo de una aplicación seria y de envergadura con garantías (como también otros frameworks), y después de un tiempo trabajando con él, puedo añadir que disfrutando mientras lo hacemos.

Desde este blog vamos a poner nuestro granito de arena para ayudaros a ponerlo a funcionar, con ejemplos prácticos reales que vayan algo más allá que un sencillo hola mundo, y compartir la experiencia de conocer esta potente herramienta.

¡¡ EMPEZAMOS !!


(1) Si ves que puedes aportar y mejorar una librería o Bundle que has encontrado, ¡¡ colabora !!. La inmensa mayoría son de código abierto, con sus repositorios en GitHub, gestionado por equipos entusiasmados por que otros desarrolladores participen.