Buenas prácticas y consejos para mejorar tu código en Symfony

  • 30 marzo 2017
  • Jordi Mahiques
  • Lectura: 6 minutos

Symfony es un framework PHP que recientemente ha cumplido los 500 Millones de descargas y es conocido por su gran ecosistema de componentes. También es la base de proyectos como drupal, magento y prestashop(en sus fases iniciales al port hacia symfony) entre otros. Cuenta con una comunidad muy activa, y su creador está entre los miembros del PHP-FIG, es por ello que desde acceseo os queremos mostrar en este articulo una serie de buenas prácticas y consejos para mejorar vuestro código en Symfony.

Una de las principales características, conjuntamente con el sistema de componentes, es la calidad de su documentación, así como un amplio repertorio de test que le proporcionan una gran aceptación por parte de la comunidad y una base muy sólida para empezar cualquier proyecto sin importar su magnitud.

Vamos a citar en primer lugar algunos tips and tricks, y acto seguido, algunas buenas prácticas, extraídas directamente desde la propia sección.

Trucos y consejos para optimizar Symfony

Existen multitud de plataformas que hacen uso de las variables de entorno para almacenar los credenciales de las aplicaciones. Recientemente, symfony (en su versión 3.3) ha publicado un componente llamado Dotenv, el cual nos permite parsear archivos .env. En nuestra aplicación, podemos añadir las variables como parámetros:

// app/AppKernel.php

public function registerContainerConfiguration(LoaderInterface $loader)
{
    $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');

    try {
        (new Dotenv\Dotenv(__DIR__.'/../'))->load();
        $envParameters = $this->getEnvParameters();
        $loader->load(function($container) use($envParameters) {
            $container->getParameterBag()->add($envParameters);
        });
    } catch (Dotenv\Exception\InvalidPathException $e) {
        // don't do much at the moment, possibly the env variables are set differently (e.g. AWS)
    }

En su versión 3.2 de symfony, se integró el uso de la función env, encargada de obtener el valor de la variable de entorno desde la configuración en yaml con el siguiente formato:

# app/config/config.yml
doctrine:
    dbal:
    # ...
        password: "%env(DB_PASSWORD)%"

En la versión 2.6 fue añadido LockHandler, y en su versión mas reciente, la 3.3, han anunciado el componente llamado Lock component, el cual nos permite bloquear el acceso a los recursos a través de diversos métodos, tales como flock de php, PHP Semaphore extension, Redis y Memcache.

Yaml, human friendly data serialization standard, mantenido por Clark C. Evans, es un standard que tiene por objetivo la serialización de la información de forma descriptiva. En los últimos años ha ganado popularidad, debido a la facilidad de parseado frente a alternativas como XML. Herramientas como Docker, también lo usan para expresar sus archivos de configuración. Symfony cuenta con un componente llamado YAML Parser. Desde la versión 3.3, ahora se nos permite crear etiquetas personalizadas.

$yaml = "!my_tag { foo: bar }";
$config = Yaml::parse($yaml, Yaml::PARSE_CUSTOM_TAGS);

$tag = $config->getTag(); // $tag = 'my_tag'
$value = $config->getValue(); // $value = array('foo' => 'bar')

Lo podemos usar para añadir funcionalidades específicas para la configuración de nuestro bundle, por ejemplo.

Como última novedad, han incorporado la carga de archivos locales con patrones globales. Ahora podemos hacer lo siguiente:

const CONFIG_EXTS = '.{php,xml,yaml,yml}';

// ...
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
    $confDir = dirname($this->getRootDir()).'/etc';
    $loader->import($confDir.'/packages/*'.self::CONFIG_EXTS, 'glob');
    $loader->import($confDir.'/packages/'.$this->getEnvironment().'/**/*'.self::CONFIG_EXTS, 'glob');
    $loader->import($confDir.'/container'.self::CONFIG_EXTS, 'glob');
}

Existe una característica del componente Config no muy conocida, que nos permite hacer override de los archivos que hemos cargado:

# app/config/config.yml
imports:
    - { resource: 'parameters.yml' }
    - { resource: '/etc/sites/mysite.com/parameters.yml', ignore_errors: true }

De esta forma, podemos tener en el servidor de producción un archivo con los parámetros correspondientes. Sin embargo, en local, como no existe dicho archivo y le hemos indicado que no lance excepción seguirá el flujo habitual de la aplicación.

Por lo que a conexión con capa de persistencia de datos se refiere, symfony usa Doctrine, un ORM (Object Relational Mapper). Los bundles con los que viene symfony, por regla general, vienen con una gran cantidad de configuración por defecto que nosotros podemos modificar según nuestras necesidades. Por lo que respecta al naming de las tablas, resulta común que la estrategia varíe según los requisitos del proyecto. Para tal propósito, podemos forzar la estrategia de naming con una configuración, para evitar la redundancia de escribir el parámetro en cada valor de la entidad en caso de pretender modificar el comportamiento habitual:

    #app/config/config.yml
        config:
            doctrine:
                dbal:
                # ...
                orm:
                    # ...
                    entity_managers:
                        default:
                            naming_strategy: doctrine.orm.naming_strategy.underscore

También podremos hacer nuestras propias estrategias de naming haciendo uso de la clase: Doctrine\ORM\Mapping\NamingStrategy según indican en su documentación.

En lo referente a su motor de plantillas, twig, hay interesantes mejoras que podemos utilizar.

Disponemos de la posibilidad de evaluar si existe un bloque, a través de la siguiente sintaxis:

{%if 'block_name' is block%}
   Esto es un bloque
{% endif %}

Cuando creamos nuestros propios filtros, y necesitamos proporcionarle un número arbitrario de parámetros de entrada, podemos usar la opción is_variadic

$filter = new Twig_Filter('thumbnail', function ($file, array $options = array()) {
// ...
}, array('is_variadic' => true));

Para finalizar, podemos usar lo que llaman, named arguments. Nos confían una mayor legibilidad en el código:

{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}

En cuanto a los logs, symfony cuenta con su propio componente, que nos ayuda identificar los estados por los cuales pasa nuestra aplicación. Es un gran desconocido,
pero cuenta con muchas funcionalidades que nos pueden ayudar identificar problemáticas futuras.

Podemos crear canales personalizados, de forma muy sencilla:

    # app/config/config.yml
    monolog:
        channels: ['foo', 'bar']

Ahora symfony ya permite pasar el canal de log a través de un argumento:

#app/config/config.yml
services:
    some_service:
        class: Namespace\Some\Service
        arguments: ["@monolog.logger.alert"]

Podemos crear formatters personalizados desde la configuración, sin necesidad de implementar una clase de formateo:

#config.yml
services:
    app.log.formatter:
        class: Monolog\Formatter\LineFormatter
        public: false
        arguments:
            - '%%level_name%% [%%datetime%%] [%%channel%%] %%message%%\n' #mensaje a escribir en el archivo de log
            - 'H:i:s' #formato
            - false #ignorar \n en los logs

Configurando donde queremos usar dicho formato:

#app/config/config.yml
monolog:
    handlers:
        main:
            formatter: app.log.formatter

Gestión de correos en entorno de desarrollo

Cuando se trata de correos, son una parte básica de cualquier aplicación, sobretodo si la aplicación tiene usuarios y deseamos verificar el correo de registro, por ejemplo. En entornos de desarrollo, es importante que los emails, sigan el flujo habitual. Así como la posibilidad de poder visualizarlos. Nosotros lidiamos con este problema con una herramienta llamada Mailhog, el cual cuenta con repositorio en github. Podemos ir a la sección releases de la documentación para encontrar la última versión compilada de la misma. Está dotado con un servidor de stmp y un panel web para visualizar todos los correos salientes de la aplicación. Es una gran opción que no necesita de instalar daemons en el caso de linux, tan sólo ejecución en el momento en que necesitemos de la funcionalidad.

En symfony tenemos una guía para organizar los entornos con diferentes archivos de configuración de manera jerárquica en función de los directorios como se muestra en la documentación. Esto nos puede servir para cargar diferentes configuraciones, como por ejemplo en este caso, que nos interesa cambiar los datos del servidor smtp para poder evaluar la aplicación al completo.

Buenas prácticas en Symfony

Por último vamos a citar algunas de las buenas prácticas a modo de resumen, que nos proporcionan desde la sección de best practices.

Configuración:

  • Define toda la configuración de la infraestructura en el archivo parameters.
  • Define todos los parámetros en parameters.yml.dist. Ten en cuenta que composer evalua este archivo para regenerar el parameters.yml.
  • Define la configuración de la aplicación en config.yml.
  • Usa constantes para definir la configuración.
  • El naming de los parámetros debería ser lo mas corto posible.

Organizar la lógica de negocio:

  • Usa nombres lo mas cortos posibles para los servicios del bundle.
  • Escribe la configuración de los servicios en archivos YAML
  • Como hemos comentado anteriormente, mueve los datos sensibles fuera de la aplicación con variables de entorno.

Controladores:

  • Los controladores deben extender siempre del controlador base de FrameworkBundle.
  • No uses la anotación @Template.
  • Usa ParamConverters para obtener la entidad en el controlador.
  • Por norma general, como indican en la documentación, los controladores deberían seguir la regla 5-10-20. 5 líneas variables o menos, 10 acciones o menos y 20 líneas o menos

Como conclusión final, symfony tiene una curva de aprendizaje en sus inicios algo elevada, pero cuando se domina el framework en sus aspectos más básicos nos puede ayudar con un ágil desarrollo con poco esfuerzo y una gran calidad del código, siguiendo unas normas básicas de buenas prácticas.

Comparte
Share on facebook
Share on twitter
Share on linkedin
¿Quieres más información?
Ponte en contacto con nosotros.
Jordi Mahiques
Jordi Mahiques
Backend developer - Departamento de desarrollo

2 thoughts on “Buenas prácticas y consejos para mejorar tu código en Symfony

  1. Hola Jordi, estoy empezando con Symfony y tengo una duda respecto a lo que comentas de tener el código de los controladores lo más reducido posible.

    Cuando el código tiene que ver con entidades, entiendo que todos los métodos tienen que ir al repositorio correspondiente, pero cuando no es el caso, ¿cual sería el sitio correcto o la estructura correcta para dejar el código y no ponerlo en los actions de los controladores?

    Muchas gracias.

    1. Buenas tardes Sergio,

      como bien sabrás hay diversas soluciones por las que puedes optar en función de la problemática. A lo que hago mención aquí, es a extraer la lógica perteneciente a los controladores, para evitar la duplicidad del código. Por norma general, siempre que copies código es una mala práctica. Hay diversas soluciones que te animo a buscar, no sin pasar por alto la documentación de symfony, que es de gran calidad.

      Saludos.

Enviar Comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Artículos relacionados

Suscríbete a nuestra newsletter
para estar al día en el mundo online
¿Alguna incidencia?

Cuéntanos qué ocurre
y nos pondremos con ello lo antes posible.

¡Cuéntanos tus ideas!
+34 96 653 19 14
+info@acceseo.com
He leído y acepto la política de privacidad