Symfony 4: Estructura de directorios

Symfony 4 se publicará en Noviembre de 2017. Esta serie de artículos explica sus principales novedades:


Uno de los principales cambios introducidos en Symfony 3 fue su nueva estructura de directorios. En Symfony 4 vamos a hacer algunos retoques a esa estructura para adaptarla a las nuevas funcionalidades y a las buenas prácticas.

La estructura de directorios por defecto de los proyectos Symfony 3 tiene este aspecto:

├── app/
│   ├── autoload.php
│   ├── AppKernel.php
│   ├── config/
│   └── Resources/
│       └── views/
├── bin/
│   └── console
├── src/
│   └── AppBundle/
├── var/
│   ├── cache/
│   └── logs/
├── vendor/
└── web/

En Symfony 3 la estructura de directorios es más parecida a la de UNIX (por ejemplo, el directorio var/) y es más plana que la de Symfony 2, por lo que tiene menos subdirectorios. Los cambios de Symfony 4 van también en esa dirección.

Utilizar nombres estandarizados para los directorios de la aplicación reduce la curva de aprendizaje. Por eso fue una buena idea usar bin/, src/ y var/ como nombres. En Symfony 4, siguiendo con esta misma idea, el directorio app/ se ha renombrado a config/, que es el nombre estándar de los directorios que guardan archivos de configuración. Este cambio se propuso para Symfony 3 también, pero fue rechazado por razones que ya no son un problema en Symfony 4.

Los tests se guardan en tests/

Los tests se han movido a un directorio llamado tests/ en la raíz del proyecto. Este cambio también se propuso antes, pero ahora que el código de la aplicación ya no se guarda en bundles, tiene todo el sentido hacerlo. Este cambio también permite mejorar el rendimiento de la aplicación, ya que facilita separar las clases de los tests respecto al resto de clases:

{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    },
    "autoload-dev": {
        "psr-4": { "App\\Tests\\": "tests/" }
    }
}

Las plantillas se guardan en templates/

Las plantillas ahora son un elemento de primer nivel en las aplicaciones porque se guardan en el directorio templates/ en la raíz del proyecto. Aunque, ¿quizás deberíamos cambiarlo por tpl para seguir con la idea de los directorios de tres letras?

¿Y por qué no seguir con el nombre views/ de Symfony 3? Originalmente, elegimos views como nombre de esta carpeta porque era más corto que templates. Pero esto fue un error, ya que en el ámbito de la programación, View es un concepto diferente al de las plantillas. Así que por fin hemos podido solucionar este error.

Tener las plantillas en un directorio de primer nivel también hace más fácil el trabajo de los diseñadores web. Además, este directorio templates/ solo se crea cuando instalas Twig.

Una de las consecuencias de mover las plantillas a templates/ es que el directorio src/ ahora está reservado exclusivamente para clases PHP. Otra buena consecuencia de no utilizar bundles.

La configuración se guarda en config/

El nuevo directorio config/ es equivalente al anterior directorio app/config/, pero con una organización diferente. Para empezar, como ya dijimos en el anterior artículo, los archivos parameters.yml y parameters.yml.dist desaparecen.

El principal punto de entrada de la configuración es el nuevo archivo container.yaml. Inicialmente está vacío y ahí es donde defines tus servicios y parámetros. La configuración de los bundles de terceros que instalas con Composer se guarda en archivos individuales. Un archivo por cada bundle y cada entorno de ejecución. Y lo mismo sucede con la configuración del enrutamiento. Aunque estos cambios son necesarios para poder implementar la instalación/desinstalación automática de bundles, lo cierto es que permite una mejor organización de la configuración.

Al igual que en Symfony 3, los archivos de configuración se pueden seguir escribiendo en PHP, XML o YAML. La única diferencia es que los archivos YAML ahora utilizan la extensión estándar .yaml en vez de la extensión incorrecta .yml que utilizábamos hasta ahora.

Otro cambio importante es la introducción de un nuevo archivo llamado bundles.php y que contiene la referencia de todos los bundles instalados y los entornos en los que están activados.

Tener un archivo de configuración por bundle y la creación del archivo bundles.php son las claves que permite que Symfony pueda instalar y configurar automáticamente cualquier bundle.

El código se guarda en src/

La clase Kernel se ha movido de app/ a src/, que es realmente el lugar al que pertenece. El código de esta clase es muy diferente al de Symfony 2. En primer lugar, utiliza el trait MicroKernelTrait. Además, implementa la nueva lógica para cargar los bundles mediante el archivo bundles.php y carga todos los archivos de configuración individuales. Todos estos cambios ya funcionan a partir de Symfony 3.3. Por ejemplo, este es el código que carga los archivos de configuración:

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

Los archivos temporales se guardan en var/

El directorio var/ es muy similar al de Symfony 3, pero con algunos cambios menores para adaptarse a las nuevas buenas prácticas.

En primer lugar, var/cache/ solo debe utilizarse para almacenar contenidos cacheados durante mucho tiempo: el contenedor de servicios compilado, las traducciones, los proxies de Doctrine, etc. No deberías almacenar archivos temporales en este directorio.

En otras palabras, cualquier contenido almacenado en var/cache/ debería tener una clase PHP asociada capaz de volver a generar ese contenido. La idea es que estos archivos no tienen que ser modificados nunca más una vez la aplicación está desplegada, para permitir la ejecución de aplicaciones en sistemas de archivos de solo lectura.

¿Y dónde se almacenan entonces los archivos temporales? Puedes usar cualquier otro directorio como var/tmp/ o incluso el propio directorio /tmp estándar de UNIX.

Si sigues esta recomendación, algún día podremos garantizar que el directorio var/cache/ es de solo lectura. Esto es importante porque muchas plataformas de hosting modernas (Heroku, SensioCloud, etc.) tienen sistemas de archivos de solo lectura. Además, este cambio permite escalar la aplicación de manera más sencilla. Lo malo es que todo esto seguramente no será verdad en Symfony 4.0 y habrá que esperar a las siguientes versiones.

Los archivos web se guardan en public/

En el artículo anterior explicamos que las aplicaciones Symfony ahora solo tienen un controlador frontal en el directorio public/. Casi todos los demás archivos se han eliminado: config.php, .htaccess, favicon.ico, apple-touch-icon.png y incluso robots.txt. ¿Por qué? Porque no todos los proyectos necesitan esos archivos. Pero no te preocupes porque habrá una manera sencilla de crear esos archivos si lo necesitas.

Todo es opcional

Una diferencia esencial respecto a Symfony 3 es que todos los directorios de primer nivel del proyecto son opcionales. ¿No usas por ejemplo plantillas porque estás haciendo una API? Pues no tendrás el directorio templates/. Todos los directorios se crean bajo demanda, sólo cuando los necesitas.

Cuando instales un bundle de terceros con Composer en Symfony 4, esta nueva estructura de directorios permitirá registrarlo y activarlo en el archivo bundles.php, configurarlo automáticamente en el directorio config/ y mucho más. Precisamente, ese "mucho más" será el tema del siguiente artículo.

Comentarios

Publicada el

10 de abril de 2017

Etiquetas

Proyectos Symfony destacados

La forma más sencilla de generar el backend de tus aplicaciones Symfony. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.