Symfony - Un preludio

June 18, 2021

Para aquellos Drupaleros que aún no lo conocían, Symfony es probablemente el framework más popular de PHP, contando con una comunidad lo suficientemente amplia y activa como para generar varios y distintos proyectos de software libre (Twig, Sílex, Laravel, entre otros).

Con la introducción a Drupal 8, Symfony se ha convertido en la nueva parte de la familia de Drupal (aunque sería más correcto decir que Symfony adoptó la comunidad de Drupal en su familia), lo cual ha conllevado un cambio lo suficientemente drástico en la estructura de nuestro CMS como para tomar un paso hacia atrás y analizar lo que nos trae Symfony.

Al haber tenido la oportunidad de trabajar tanto con Drupal 8 como con Symfony últimamente, decidí aprovechar este blog para plasmar mis experiencias con el framework y sus componentes.

Construyendo un REST API con Symfony

Tengo que ser honesto: hasta hace un mes, mi experiencia con Symfony era bastante limitada. Un proyecto que hemos estado desarrollando en Drupal 8 aquí en Rootstack y otro proyecto Open Source en el que he estado trabajando en Symfony han sido mi experiencia hasta ahora, y tengo que decir que hasta el momento ha sido una agradable sorpresa. Empezaré por Symfony como Framework, ya que es una base importante para entender su funcionamiento en Drupal 8.

Symfony representa tanto un conjunto reutilizables de componentes PHP (los cuales ya son utilizados en varios proyectos reconocidos, como Laravel y phpBB) como un framework independiente que permite la creación de proyectos desde cero. Con el crecimiento exponencial del proyecto de Symfony, el framework se ha convertido en uno de los más empleados para el desarrollo moderno de proyectos PHP, y con mucha razón: uno de los primeros adoptadores de Composer (manejador de dependencias de PHP inspirado en manejadores modernos como npm y bundler), Symfony aprovecha su facilidad de implementación y ejecución para crear rápidamente entornos de desarrollo listos para trabajar; además, su estructura MVC y su implementación de otros proyectos para el manejo de modelos y vistas (Twig, Silex, Propel, Doctrine, entre otros) le permite a los desarrolladores seguir patrones modernos de desarrollo en sus proyectos.

Instalar Symfony no fue muy difícil, ya que cuenta con un instalador por terminal sencillo y rápido de usar (en caso de que se esté usando Mac o Linux, Windows cuenta con su instalador alterno). Para instalar Symfony, ingresamos las siguientes líneas de comando:

$ curl -LsS http://symfony.com/installer > symfony.phar
$ sudo mv symfony.phar /usr/local/bin/symfony
$ chmod a+x /usr/local/bin/symfony

Una vez llevada a cabo la instalación, podremos comprobar su funcionamiento a través del comando por terminal symfony. Cuando el instalador se haya instalado correctamente, sólo tenemos que utilizarlo para crear nuestro nuevo proyecto, completo con la estructura y dependencias finales: symfony new myproject.

Symfony, como mencionado anteriormente, maneja una estructura MVC. Los controladores son declarados por Symfony extendiendo la clase base Controller, permitiéndonos definir las acciones y el routing de la aplicación. Las acciones vienen siendo las funciones y métodos a llamar al solicitar dato de una ruta, por lo general se analizan o compilan datos definidos y se imprime el resultado a través de una vista). Las rutas pueden ser definidas de varias formas (por anotación, YML, XML, entre otros) y se encargan de enlazar URL locales a las acciones declaradas, de forma que toda solicitud válida al servidor sea respondida por una acción determinada, la cual llame a la vista pertinente.

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
  /**
   * @Route("/", name="homepage")
   */
  public function indexAction()
  {
    return $this->render('default/index.html.twig');
  }
}

Las vistas son manejadas por Twig, en las cuales definimos la página a mostrar, con tanto de data analizada proveniente del controlador (de ser necesario). Twig también cuenta con un sistema de plantillado, el cual permite reutilizar plantillas existentes y generar nuevas.

{# app/Resources/views/default/index.html.twig #}
{% extends 'base.html.twig' %}

{% block body %}
  <h1>Welcome to Symfony!</h1>
{% endblock %}

El modelo puede implementado a través de uno de los ORM con el que viene Symfony: Propel y Doctrine. También puede ser implementado de forma manual, en caso de alguna aplicación de prueba o, en caso de desarrollos menores o más personalizados, se prefiera implementar a través de PDO.

Symfony también incluye varios componentes para facilitar el desarrollo, tanto front-end como back-end, como:

  • El componente de Formularios que permite definir en el controlador un objeto Form a partir de un modelo y pasarlo a Twig para que lo renderize fácilmente
  • El manejo de validaciones, las cuales pueden ser definidas en varios formatos (anotaciones, YML, XML, entre otros) y llamadas para validar cualquier objeto o entidad
  • Manejo de eventos, a través de los cuales podemos controlar acciones o disparadores a llevar a cabo en determinados momentos en el ciclo de vida de la aplicación (al recibir un request o enviar un response generalmente)
  • Un barra de herramientas que nos provee con varia información invaluable para el desarrollo de una aplicación, como tiempo y memoria de carga, consultas realizadas, rutas y callbacks invocados, y demás.

Symfony cuenta con muchos más componentes y proyectos que pueden ser implementados fácilmente. Me ha sorprendido mucho la facilidad con la que pude levantar mi proyecto y empezar a desarrollar, sin preocuparme por los detalles técnicos que a menudo vienen asociados con un framework de desarrollo (conexiones a base de datos, interoperabilidad de módulos y componentes, rendimiento del servidor, para mencionar algunos). ¿Será que la implementación de Symfony en Drupal ayudará a bajar la famosa curva de dificultad de nuestro CMS?

Symfony en Drupal 8

Como era de esperarse, en la nueva versión de Drupal, muchas cosas han cambiado, sobre todo para los que ya han desarrollado sitios en versiones anteriores. La pregunta es, ¿qué tanto ha cambiado con la adopción de Symfony?

En pocas palabras, mucho, pero para mejor. Esta es la impresión que me he llevado al manejar Drupal 8 en los últimos meses. A continuación discutiré mis experiencias al respecto.

Una vez realizado el proceso de instalación y de haber navegado por la nueva UI de administración, me dispuse a investigar sobre el manejo del core para la creación de los varios elementos básicos (forms y bloques para empezar). Desde aquí se puede ver las mejoras en el manejo de los elementos del core, ahora manejados por objetos en formato PSR-4 (alejándose del sistema basado en hooks, pero esto ya es material para otro blog).

Sin embargo, los cambios más drásticos que son tomados directamente de Symfony son:

  1. Routing: El manejo de rutas ya abandonó el manejo de hook_menu, utilizando en su lugar el sistema de manejo de rutas de Symfony. Las rutas son declaradas en formato YML y son cargadas y cacheadas por el bootstrap de Drupal, facilitando el manejo de los URL, evitando la necesidad de consultar a todos los hooks del sistema y facilitando la integración con los demás componentes.
  2. YAML: Probablemente uno de los mejores cambios en Drupal 8, el componente de parsing de YML de Symfony y su integración para el uso del formato en varios otros componentes ha impulsado la estructura de configuración en archivo, reemplazando el muy conocido Features y permitiendo a todo site admin y site builder exportar a código toda la configuración de nuestro sitio de forma fácil, rápida e integrada, facilitando el desarrollo en equipos de varias personas.
  3. EventDispatcher: A través del EventDispatcher, Drupal 8 puede invocar eventos y esperar la llamada de los mismos en otros módulos, reemplazando efectivamente a module_invoke de forma más eficiente con los recursos.
  4. Twig: Aunque funcionalmente Twig y PHPTemplate sean bastantes parecidos, el manejo más limpio de las funciones en Twig y su sintaxis más sencilla nos permite realizar vistas sin preocuparnos de código PHP de lógica que pueda ser ingresado en la vista (lo cual desafortunadamente he visto pasar en varias ocasiones), además de contar con funciones de utilidad que vienen con Twig y son fáciles de implementar.
  5. Inyección de Dependencias: El sistema de inyección de dependencias de Symfony es el que usa Drupal al crear e instanciar los objetos reutilizables implementados por el core, como los Forms y bloques, facilitando el manejo del código.

Aunque definitivamente aún hay varios elementos que Drupal 8 sigue usando desde sus versiones anteriores (como por ejemplo el Form API), a lo largo del beta se ha estado haciendo un esfuerzo para remover elementos originales del API de Drupal que sean redundantes, para que se implementen directamente los de Symfony a donde sea posible. Algunos ejemplos de esta estrategia son: La remoción del Drupal Watchdog en favor de Monolog (el sistema de manejo de logs que viene con Symfony); la remoción de la función para hipervínculos l() en favor del manejo de objetos Url, que invocan a las rutas definidas en el sistema; la implementación de varias funciones del Drupal core en forma de eventos y servicios, entre otros.

Como resultado del manejo de estos dos proyectos, aparentemente diferentes pero relacionados, he podido llegar a la conclusión de que Symfony es un framework que definitivamente voy a estar manejando más en el futuro, suficientemente estable y maduro y, al mismo tiempo, fácil de implementar para desarrollar una plataforma de PHP. La implementación de Symfony con Drupal puede que aleje a varios de sus usuarios que provienen de versiones anteriores, pero aquellos que ya tengan experiencia en Symfony, o que decidan quedarse para averiguar las diferencias, encontrarán un sistema que permita el manejo mucho más estructurado y profesional de los elementos de site building que necesitemos para desarrollar en Drupal, acercándonos más a estándares de desarrollo más eficientes.