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!

18
Login or Register to join the conversation
Lechu85 Avatar

After this part of course or previous i have get a list of warinig like this:

warning: in the working copy of 'src/Repository/CommentRepository.php', LF will be replaced by CRLF the next time Git touches it

can you tell me what to do with that? :)

Reply

Hi

Yeah, that sometimes happens when you are working on windows. The best solution is configuring your editor to use LF as line endings. In PHPStorm you can do it in the bottom right corner.

Cheers

Reply
Steve-D Avatar

Hi

I'm now going through the tutorial again using my own Symfony 5 project but when updating the symfony/frameworkbundle recipe, my code is deleted in favour of the new code. I'm not getting the conflict (ours/theirs)

Am I missing something?

Thank you Steve

Reply

Hey Steve,

Did you notice any warnings/errors in the console when was doing that upgrade? Well, it might be so that your symfony.lock file was in not-perfect state. It happens sometimes, but that's to the "git diff" you should be able to revert your original configuration manually.

I hope this helps!

Cheers!

Reply
Steve-D Avatar

Thank you Victor. There were no errors in the console. I did start to get conflicts later on in some areas though. I pulled the code that was removed from a copy of the project so nothing has been lost.

Thank you

Reply

Hey Steve,

Awesome, glad to hear you nailed it. Yeah, it might be some edge cases probably, not sure if those are bugs or no. If you noticed a weird behaviour that looks like a bug and you have steps how to reproduced. it - feel free to report about it in Symfony.

Cheers!

Reply
Steve-D Avatar

Hi

After running "composer require symfony/runtime" I get the following error when trying to view the site.

Cannot autowire service "App\Controller\QuestionController": argument "$isDebug" of method "__construct()" is type-hinted "bool", you should configure its value explicitly.

Have I missed something?

Thank you

Steve

Reply
Victor Avatar Victor | SFCASTS | Steve-D | posted hace 5 meses | HIGHLIGHTED

Hey Steve,

Did you download the course code and started from the start/ directory there? It sounds like you're missing some code in your project, most probably something that were added in previous tutorials. So, I'd recommend you to follow the tutorial this way.

But what about the actual error, make sure you have this code in your config/services.yaml


services:
# default configuration for services in *this* file
_defaults:
# ...
bind:
bool $isDebug: '%kernel.debug%'

If you have this - the autowiring should work. But also, please, make sure you typehinted that argument as "bool $isDebug" in the __construct(). And don't forget to clear the cache just in case to rule out the cache problem :)

Cheers!

1 Reply
Ek24 Avatar

i had, beside others, the same error. adding

        bind:
            bool $isDebug: '%kernel.debug%'

to servcices.yaml fixed the problem.

yes, i used the start folder from the zip.

Reply

Hey Ek24,

Thanks for confirming this configuration helped!

Cheers!

Reply
Steve-D Avatar

HI Victor

I did download the course code yes and have since (in the last few mins) sussed out a couple of things. I crossed referenced the "finish" code making a few tweaks (mainly the one you have suggested) and also found that PhpStorm was using php7.4. Changing this has now got me in the right place.

Thank you so much for replying

Steve

Reply

Ah, I thought you get the error in your browser :) Yes, PhpStorm also have runtime checks that are based on the PHP version you set in config, good catch!

I'm glad you got it working ;)

Cheers!

Reply

I don't know if it's only me, but this course is already hard to follow. After the recipes:update I've got only this.


deleted: app/config/bootstrap.php
deleted: app/config/packages/test/framework.yaml
deleted: app/config/routes/dev/framework.yaml
modified: app/symfony.lock

Reply
MikkoP Avatar

Hi,
I had the same, really confusing result. You probably also have new .git -folder in your current directory, but with only objects subdir in it?

After digging deeper what happens it seems that recipes:update does not work properly when your symfony project is in a subfolder of your git project.
(Git diff in RecipePatcher assumes you are at the root of the git project, and the same with paths to .git -folders when generating and adding the blobs.)

I think I know already how this could be fixed. But as a quick fix to get further with the course, you can try working on a git repo where you are at the root folder.

Best Regards,
Mikko

1 Reply

Hey Mikko,

Oh, it might be so... I personally init Git repo for all my projects in the root dir of the Symfony project, that's why I probably have never noticed it myself. Thanks for sharing this tip! Well, I'm not sure if this behaviour would be considered as a bug, but I think it's worth to be reported upstream if it has not been reported yet.

Cheers!

Reply

Hey Julien,

This does not sound like a desired behaviour... seems something went wrong, and probably the command output has more context. Btw, what command did you execute? Well, you may want to "reset" the recipe, I suppose you're talking about symfony/framework-bundle one? You can do it with

$ composer recipe:install symfony/framework-bundle --force --reset

It will force install the latest recipe overwriting the existent data, but then with "git diff" you may revert some good changes you want to keep.

I hope this helps!

Cheers!

Reply

Hum, I did reset the head and all the files and ran

$ composer recipes:update

chose symfony/framework-bundle and got the same 4 file updates only.

Then, I did a reset again to have a clean branch and ran

$ composer recipe:install symfony/framework-bundle --force --reset

which gave something closer to the expected result

You can check my setup if you want to: https://github.com/jbonnier...

Just run

$ make local-config
$ docker compose up -d

Nginx might crash if you don't have an SSL certificate in a certain path, but you shouldn't need a web server for that.

Also all my composer commands are ran in a container with

$ docker compose exec php-cli composer ...

Reply

Hey Julien,

Yeah, not sure what happened, but "recipe:install --force --reset" should do the trick because it literally just re-install the latest recipe from scratch. A trick I use sometimes if something went wrong with "recipe:update" command.

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

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