Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Actualizar la importante receta de FrameworkBundle

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

En tu terminal, ejecuta:

composer recipes

Como probablemente sabes, cada vez que instalamos un nuevo paquete, ese paquete puede venir con una receta que hace cosas como añadir archivos de configuración, modificar ciertos archivos como .env, o añadir otros archivos. Con el tiempo, Symfony realiza actualizaciones de estas recetas. A veces son menores... como la adición de un comentario en un archivo de configuración. Pero otras veces, son mayores, como cambiar el nombre de las claves de configuración para que coincidan con los cambios en el propio Symfony. Y aunque no tienes que actualizar tus recetas, es una gran manera de mantener tu aplicación como una aplicación estándar de Symfony. También es una forma gratuita de actualizar el código obsoleto

Hola recipes:update

Hasta hace poco, la actualización de las recetas era un dolor de cabeza. Si no estás familiarizado, ¡consulta nuestro tutorial "Actualizar a Symfony 5"! Yikes. ¡Pero ya no! A partir de Symfony Flex 1.18 o 2.1, Composer tiene un comando propio recipes:update. Literalmente, parchea tus archivos a la última versión... y es increíble. ¡Vamos a probarlo!

Ejecuta:

composer recipes:update

Antes de ejecutar esto, nos dice que confirmemos todo lo que hemos estado trabajando. ¡Gran idea! Diré que estamos

actualizando algo de código a Symfony 5.4 con Rector

git add .
git commit -m "upgrading some code to Symfony 5.4 with Rector"

¡Perfecto! Prueba de nuevo el comando recipes:update. La razón por la que quiere que nuestra copia de trabajo esté limpia es porque está a punto de parchear algunos archivos... lo que podría implicar conflictos.

Empecemos por symfony/framework-bundle, porque es el más importante. Los archivos más importantes de nuestro proyecto provienen de esta receta. Voy a pulsar 4, despejar la pantalla, y ¡adelante!

Entre bastidores, esto comprueba el aspecto de la receta cuando la instalamos originalmente, lo compara con el aspecto actual de la receta y genera un diff que luego aplica a nuestro proyecto. En algunos casos, como éste, esto puede causar algunos conflictos, lo cual es bastante genial. La mejor parte puede ser que genera un registro de cambios que contiene todos los pull requests que han contribuido a estas actualizaciones. Si necesitas averiguar por qué ha cambiado algo, esto será tu amigo.

Ah, pero crear el registro de cambios requiere hacer un montón de llamadas a la API de GitHub, así que es posible que Composer te pida un token de acceso personal, como acaba de hacer conmigo. En algunos casos raros con una receta gigante como framework-bundle, si tu receta es muy, muy antigua, puede que te aparezca este mensaje aunque hayas dado un token de acceso a Composer. Si esto ocurre, sólo tienes que esperar 1 minuto... y volver a introducir tu código de acceso. Enhorabuena, acabas de alcanzar el límite de la API por minuto de GitHub.

De todos modos, ahí está el CHANGELOG. No suele ser tan largo, pero esta receta es la más importante y... bueno... estaba horriblemente desactualizada. Ah, y si tienes un terminal de moda como yo -esto es iTerm- puedes hacer clic en estos enlaces para saltar directamente al pull request, que vivirá en https://github.com/symfony/recipes.

Cambios en el .env

Muy bien, vamos a repasar los cambios que ha hecho esto. Esta es la receta más grande e importante, así que quiero cubrir todo.

Como ya he hecho los deberes, borraré el registro de cambios y correré:

git status

Woh. Ha hecho un montón de cambios, incluyendo tres conflictos. ¡Qué divertido! Vamos a verlos primero. Muévete y empieza dentro de .env. Veamos: aparentemente la receta eliminó estas líneas #TRUSTED_PROXIES y #TRUSTED_HOSTS

32 lines .env
... lines 1 - 15
###> symfony/framework-bundle ###
... lines 17 - 18
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
#TRUSTED_HOSTS='^(localhost|example\.com)$'
###
... lines 22 - 32

Ambas se establecen ahora en un archivo de configuración. Y aunque todavía puedes establecer una variable de entorno y hacer referencia a ella desde ese archivo de configuración, la receta ya no incluye estos comentarios. No estoy seguro de por qué esto ha causado un conflicto, pero vamos a eliminarlos.

Cambios en services.yaml

El siguiente conflicto está en config/services.yaml. Este es bastante sencillo. Esta es nuestra configuración y abajo, la nueva configuración. La receta ha eliminado la entrada App\Controller\. Esto... nunca fue necesario a no ser que hagas controladores súper elegantes que no extiendan AbstractController. Se eliminó de la receta por simplicidad. También parece que la receta actualizada reformatea el exclude en varias líneas, lo que está bien. Así que tomemos su versión por completo.

... lines 1 - 8
services:
... lines 10 - 18
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
... lines 25 - 30

Cambios en src/Kernel.php

El conflicto final está en src/Kernel.php... donde puedes ver que nuestra parte tiene un montón de código... y la suya no tiene nada.

¿Recuerdas que mencioné que configureRoutes() se trasladó a MicroKernelTrait? Pues resulta que todos estos métodos se trasladaron a MicroKernelTrait. Así que, a menos que tengas alguna lógica personalizada -lo que es bastante raro-, puedes borrarlo todo.

12 lines src/Kernel.php
... lines 1 - 7
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}

Bien, de vuelta al terminal, vamos a añadir esos tres archivos:

git add .env config/services.yaml src/Kernel.php

Y luego ejecuta

git status

para ver qué más ha hecho la actualización de la receta.

Se ha actualizado public/index.php y se ha eliminado bootstrap.php

Interesante. Eliminó config/bootstrap.php y modificó public/index.php. Están relacionados. Mira el diff de index.php:

git diff --cached public/index.php

Este archivo solía requerir config/bootstrap.php. Y el trabajo de ese archivo era leer y configurar todas las variables de entorno:

git diff --cached config/

Vamos a ver el nuevo public/index.php. Aquí está. Ahora esto requiere vendor/autoload_runtime.php. Y el archivo es mucho más corto que antes. Lo que estamos viendo es el nuevo componente Runtime de Symfony en acción

10 lines public/index.php
... lines 1 - 4
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};

Puedes consultar su entrada de blog de introducción para saber más sobre él.

Básicamente, el trabajo de arrancar Symfony y cargar todas las variables de entorno se ha extraído al componente Runtime. Pero... en realidad aún no tenemos ese componente instalado... por lo que, si intentamos actualizar la página, lo pasaremos mal:

No se ha podido abrir autoload_runtime.php.

Para solucionar esto, dirígete a tu terminal y ejecuta

composer require symfony/runtime

Este paquete incluye un plugin de Composer... por lo que nos preguntará si confiamos en él. Di "sí". Entonces se instala... ¡y enseguida explota cuando intenta borrar la caché! Ignora eso por ahora: lo arreglaremos en unos minutos. Se trata de actualizar otra receta.

Pero si probamos nuestro sitio... ¡funciona!

Nueva configuración específica del entorno

Bien, ¡ya casi hemos terminado! De vuelta al terminal, veamos qué más ha cambiado:

git status

Fíjate en que ha eliminado config/packages/test/framework.yaml, pero ha modificadoconfig/packages/framework.yaml. Este es probablemente el cambio más común que verás cuando actualices tus recetas hoy.

Abre config/packages/framework.yaml. Al final... hay una nueva sección when@test

... lines 1 - 19
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file

A partir de Symfony 5.3, ahora puedes añadir una configuración específica del entorno utilizando esta sintaxis. Esta configuración solía vivir dentro de config/packages/test/framework.yaml. Pero para simplificar, la receta ha eliminado ese archivo y sólo ha movido esa configuración al final de este archivo.

De vuelta al terminal, difunde ese archivo... que esconde otros dos cambios:

git diff --cached config/packages/framework.yaml

La receta también cambió http_method_override por false. Eso desactiva, por defecto, una función que probablemente no estabas utilizando de todos modos. También ha cambiadostorage_factory_id por session.storage.factory.native. Esto tiene que ver con cómo se almacena tu sesión. Internamente, la clave cambió de storage_id astorage_factory_id, y ahora debería estar configurada.

Configuración del enrutamiento específico del entorno

De vuelta al terminal, veamos los cambios finales:

git status

Hablando de configuración específica del entorno, puedes hacer el mismo truco con los archivos de enrutamiento. ¿Ves cómo ha eliminado config/routes/dev/framework.yaml, pero ha añadidoconfig/routes/framework.yaml? Si abrimos config/routes/framework.yaml, ¡sí! tiene when@dev e importa las rutas que nos permiten probar nuestras páginas de error.

when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

Este es otro ejemplo de cómo la receta mueve la configuración fuera del directorio de entorno y dentro del archivo de configuración principal... sólo por simplicidad.

El nuevo archivo preload.php

Por último, la receta ha añadido un archivo config/preload.php. Éste es bastante sencillo, y aprovecha la funcionalidad de precarga de PHP

... lines 1 - 2
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
}

Básicamente, en producción, si apuntas tu php.ini, opcache.preload a este archivo, ¡obtendrás un aumento de rendimiento gratuito! Es así de sencillo. Bueno... casi así de sencillo. Lo único que tienes que hacer es reiniciar tu servidor web en cada despliegue... o PHP-FPM si lo utilizas. En SymfonyCasts lo aprovechamos para aumentar el rendimiento.

Y... ¡uf! La mayor actualización de la receta está hecha. Así que vamos a añadirlo todo y a confirmarlo. Porque a continuación, ¡más actualizaciones de recetas! Pero con FrameworkBundle detrás de nosotros, el resto será más fácil y rápido.

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^8.0.2",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "babdev/pagerfanta-bundle": "^3.6", // v3.6.1
        "composer/package-versions-deprecated": "^1.11", // 1.11.99.5
        "doctrine/annotations": "^1.13", // 1.13.2
        "doctrine/dbal": "^3.3", // 3.3.5
        "doctrine/doctrine-bundle": "^2.0", // 2.6.2
        "doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
        "doctrine/orm": "^2.0", // 2.11.2
        "knplabs/knp-markdown-bundle": "^1.8", // 1.10.0
        "knplabs/knp-time-bundle": "^1.18", // v1.18.0
        "pagerfanta/doctrine-orm-adapter": "^3.6", // v3.6.1
        "pagerfanta/twig": "^3.6", // v3.6.1
        "sensio/framework-extra-bundle": "^6.0", // v6.2.6
        "sentry/sentry-symfony": "^4.0", // 4.2.8
        "stof/doctrine-extensions-bundle": "^1.5", // v1.7.0
        "symfony/asset": "6.0.*", // v6.0.7
        "symfony/console": "6.0.*", // v6.0.7
        "symfony/dotenv": "6.0.*", // v6.0.5
        "symfony/flex": "^2.1", // v2.1.7
        "symfony/form": "6.0.*", // v6.0.7
        "symfony/framework-bundle": "6.0.*", // v6.0.7
        "symfony/mailer": "6.0.*", // v6.0.5
        "symfony/monolog-bundle": "^3.0", // v3.7.1
        "symfony/property-access": "6.0.*", // v6.0.7
        "symfony/property-info": "6.0.*", // v6.0.7
        "symfony/proxy-manager-bridge": "6.0.*", // v6.0.6
        "symfony/routing": "6.0.*", // v6.0.5
        "symfony/runtime": "6.0.*", // v6.0.7
        "symfony/security-bundle": "6.0.*", // v6.0.5
        "symfony/serializer": "6.0.*", // v6.0.7
        "symfony/stopwatch": "6.0.*", // v6.0.5
        "symfony/twig-bundle": "6.0.*", // v6.0.3
        "symfony/ux-chartjs": "^2.0", // v2.1.0
        "symfony/validator": "6.0.*", // v6.0.7
        "symfony/webpack-encore-bundle": "^1.7", // v1.14.0
        "symfony/yaml": "6.0.*", // v6.0.3
        "symfonycasts/verify-email-bundle": "^1.7", // v1.10.0
        "twig/extra-bundle": "^2.12|^3.0", // v3.3.8
        "twig/string-extra": "^3.3", // v3.3.5
        "twig/twig": "^2.12|^3.0" // v3.3.10
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.1
        "phpunit/phpunit": "^9.5", // 9.5.20
        "rector/rector": "^0.12.17", // 0.12.20
        "symfony/debug-bundle": "6.0.*", // v6.0.3
        "symfony/maker-bundle": "^1.15", // v1.38.0
        "symfony/var-dumper": "6.0.*", // v6.0.6
        "symfony/web-profiler-bundle": "6.0.*", // v6.0.6
        "zenstruck/foundry": "^1.16" // v1.18.0
    }
}