Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Automatizar las actualizaciones con Rector

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.

Ahora que estamos en Symfony 5.4, nuestro trabajo es sencillo: buscar y actualizar todo nuestro código obsoleto. Tan pronto como hagamos eso, será seguro actualizar a Symfony 6. Eso es porque la única diferencia entre Symfony 5.4 y 6.0 es que todas las rutas de código obsoleto se eliminan.

Afortunadamente, Symfony es increíble y nos dice -a través de la barra de herramientas de depuración web- exactamente qué código está obsoleto. Pero entender lo que significa todo esto... no siempre es fácil. Así que antes de intentarlo, vamos a automatizar todo lo posible, y lo haremos con una herramienta llamada Rector.

Instalación de Rector

Dirígete a https://github.com/rectorphp/rector. Se trata de una impresionante herramienta de línea de comandos con un único trabajo: automatizar todo tipo de actualizaciones de tu código, como actualizar tu código de compatible con Symfony 5.0 a compatible con Symfony 5.4. O actualizar tu código para que sea compatible con PHP 8. Es una herramienta poderosa... y si quieres aprender más sobre ella, incluso han publicado un libro en el que puedes profundizar... y también ayudar a apoyar el proyecto.

Muy bien, ¡vamos a instalar esta cosa! Dirígete a tu terminal y ejecuta:

composer require rector/rector --dev

¡Hermoso! Para que rector funcione, necesita un archivo de configuración. Y podemos arrancar uno ejecutando rector con:

./vendor/bin/rector init

¡Impresionante! Eso crea el archivo rector.php... que podemos ver en la raíz de nuestro proyecto. Dentro de esta función de devolución de llamada, nuestro trabajo consiste en configurar qué tipos de actualizaciones queremos aplicar. Esto se llama "reglas" o a veces "listas de conjuntos" o reglas. Vamos a empezar con un conjunto de actualizaciones de Symfony.

Configurar Rector para la actualización de Symfony

¡Si echas un vistazo a la documentación, verás un enlace a un repositorio de Symfony donde te habla de un montón de "reglas" de Symfony -palabra elegante para "actualizaciones"- que ya han preparado! ¡Muy amable por su parte!

A continuación, copia el interior de su función callback... y pégalo sobre lo que tenemos. Esto apunta a Rector a un archivo de caché que le ayuda a hacer su trabajo... y lo más importante, le dice a Rector que queremos actualizar nuestro código para que sea compatible con Symfony 5.2, así como actualizar nuestro código a algunas normas de calidad de código de Symfony y de inyección de "constructores". Si quieres saber más sobre lo que hacen, puedes seguir las constantes para ver el código.

Pero, espera, ¡no queremos actualizar nuestro código a Symfony 5.2! Queremos actualizarlo por completo a Symfony 5.4. Podrías esperar que pusiera simplemente "54" aquí. Y podríamos hacerlo. Pero en lugar de eso, voy a utilizarSymfonyLevelSetList::UP_TO_SYMFONY_54. Oh... parece que también tengo que añadir una declaraciónuse para SymfonySetList::. Déjame volver a escribir eso, pulsar "tab" y... ¡genial!

En fin. Tenemos que actualizar nuestro código de la 5.0 a la 5.1... luego de la 5.1 a la 5.2... y así hasta la Symfony 5.4. Eso es lo que significa UP_TO_SYMFONY_54: incluirá todas las "reglas" para actualizar nuestro código a la 5.1, 5.2, 5.3 y finalmente a la 5.4.

Y... ¡ya está! Estamos listos para ejecutar esto. Pero antes de hacerlo, tengo curiosidad por saber qué cambios hará esto. Así que vamos a añadir todos los cambios a git... y a confirmarlos. ¡Perfecto!

Ejecutar Rector

Para ejecutar Rector, digamos ./vendor/bin/rector process src/. También podríamos dirigirlo a los directorios config/ o templates/... pero la gran mayoría de los cambios que hará se aplican a nuestras clases en src/:

vendor/bin/rector process src/

Y... ¡funciona! ¡Espectacular! El rector ha cambiado ocho archivos. Desplacémonos hasta la parte superior. Esto es genial: te muestra el archivo que se modificó, el cambio real y, debajo, qué reglas causaron ese cambio.

Una de las modificaciones que hizo es UserPasswordEncoderInterface aUserPasswordHasherInterface. Es un buen cambio: la antigua interfaz queda obsoleta en favor de la nueva. También cambió UsernameNotFoundException porUserNotFoundException. Otra buena actualización de bajo nivel de un código obsoleto.

También hubo un cambio en una clase en Kernel... y algunas otras cosas similares. Cerca del final, la lista de conjuntos de calidad de código Symfony añadió un tipo de retorno Response a cada controlador. Eso es opcional... ¡pero bonito!

Así que no hizo una tonelada de cambios, pero arregló algunas desaprobaciones sin que tuviéramos que hacer nada.

Aunque... no es perfecto. Un problema es que, a veces, Rector se mete con tu estilo de codificación. Eso es porque Rector no entiende realmente cuál es tu estilo de codificación... y por eso ni siquiera lo intenta. Pero eso es por diseño y será fácil de arreglar.

En segundo lugar, aunque cambió la interfaz de UserPasswordEncoderInterface aUserPasswordHasherInterface, inlineó todo el nombre de la clase... en lugar de añadir una declaración use.

Y tercero, no cambió ningún nombre de variable. Así que aunque cambió este argumento a UserPasswordHasherInterface, el argumento sigue llamándose$passwordEncoder... junto con la propiedad. Y lo que es peor, elUserPasswordHasherInterface tiene un método diferente... y no actualizó el código aquí abajo para utilizar ese nuevo nombre de método.

Así que Rector es un gran punto de partida para captar un montón de cambios. Pero vamos a tener que coger lo que hemos encontrado y terminar el trabajo. Hagamos eso a continuación. Haremos parte de eso a mano... pero gran parte automáticamente con PHP CS Fixer.

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
    }
}