Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Upgrading to Symfony 5.4

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.

Step one to upgrading our app to Symfony 6 is to upgrade all of the Symfony libraries to 5.4. And... that's pretty easy: it's just a composer thing.

Tweaking the Composer Version Constraints

In composer.json, we have quite a few libraries that start with symfony/. Most of these are part of the "main" Symfony project and they follow Symfony's familiar versioning, with versions like 5.0, 5.1, up to 5.4 and then 6.0. Those are the packages that we're going to focus on upgrading.

But a few of these, like symfony/maker-bundle, follow their own versioning scheme. What a diva! We're not going to worry about upgrading those right now, but we will make sure that, by the end, we've upgraded everything.

Okay, what we need to do is change all of these 5.0.* to 5.4.*. I'm going to do a "Find & Replace" to replace 5.0.* with 5.4.*. Hit "Replace All".

108 lines composer.json
{
... lines 2 - 5
"require": {
... lines 7 - 21
"symfony/asset": "5.4.*",
"symfony/console": "5.4.*",
"symfony/dotenv": "5.4.*",
... line 25
"symfony/form": "5.4.*",
"symfony/framework-bundle": "5.4.*",
... line 28
"symfony/property-access": "5.4.*",
"symfony/property-info": "5.4.*",
"symfony/proxy-manager-bridge": "5.4.*",
"symfony/routing": "5.4.*",
"symfony/security-bundle": "5.4.*",
"symfony/serializer": "5.4.*",
"symfony/stopwatch": "5.4.*",
"symfony/twig-bundle": "5.4.*",
... line 37
"symfony/validator": "5.4.*",
... lines 39 - 44
},
"require-dev": {
... line 47
"symfony/debug-bundle": "5.4.*",
... lines 49 - 51
"symfony/web-profiler-bundle": "5.4.*",
... line 53
},
... lines 55 - 100
"extra": {
"symfony": {
"allow-contrib": false,
"require": "5.4.*"
}
}
}

Nice! And notice that, in addition to the packages themselves, we also needed to change the extra.symfony.require key. This is a performance optimization from Flex: it basically makes sure that Flex only considers Symfony packages that match this version. Just make sure that you don't forget to update it.

Ok... let's see. This updated a lot of libraries. To make sure we didn't miss anything, search for symfony/... and scroll down a bit. The monolog-bundle has its own versioning, so that's ok. But, ooh... I did miss one: symfony/routing. For some reason, this was already at Symfony 5.1. So let's change that to 5.4.* as well.

And... everything else looks okay: each is changed to 5.4.* or it has its own versioning strategy... and we're not going to worry about it right now.

Updating the Dependencies

To actually update these, over at your terminal, we could try to upgrade just the Symfony packages with:

composer up 'symfony/*'

There's a good chance that's going to fail... because in order to upgrade all of the Symfony packages, some other package will need to be upgraded, like symfony/proxy-manager-bridge. If you wanted to, you could add that to the composer up command... or add the -W flag, which tells Composer to upgrade all of the symfony/ libraries and their dependencies.

But... I'm going to upgrade everything with:

composer up

Look: in our composer.json file, the version constraints on all of the packages (Symfony and other libraries) are really good! They allow minor version updates, like 4.0 to 4.1, but they don't allow major version updates. So if there were a new version 5 of this library, running composer up would not upgrade to that new major version.

In other words, updating should only upgrade minor versions... and those, in theory, won't contain any breaks. So let's do this:

composer up

And... hello upgrades! Wow! Look at that huge list! Lots of Symfony stuff... but plenty of other libraries too.

Ok, so that was a big upgrade. Does the site still work? I don't know! Head over, refresh and... it does! Symfony is amazing!

Checking out the Deprecations

Now that we're on Symfony 5.4, we can see the full list of deprecated code paths that we hit when rendering this page. Your number will vary... and the number might even change when you refresh the page... that's due to some pages using cache. It looks like I have about 71 deprecations.

If you click into this, so cool. We can see what all of those are.

So at this point, our job is simple... but not necessarily easy. We need to hunt down every single one of these deprecations, figure out what code needs to change, and then make that change. Some of these will be pretty obvious... and some of them won't.

So before we even attempt to hunt them down manually, let's... do something more automatic. We're programmers right! Let's use a tool called Rector to automate as many changes to our code as possible. That's next.

Leave a comment!

9
Login or Register to join the conversation

During composer up get error

Compile Error: Declaration of ContainerBpUs7F4\EntityManager_9a5be93::refresh($entity) must be compatible with Doctrine\ORM\EntityManager::refresh($entity, ?int $lockMode = null)

Reply
MolloKhan Avatar MolloKhan | SFCASTS | Mepcuk | posted 5 months ago | HIGHLIGHTED

Hey Mepcuk,

That's unexpected, could you try clearing the cache manually? rm var/cache/*

Cheers!

3 Reply

Hey MolloKhan,

That works, thanks. Only correct command will be rm -R var/cache/*

1 Reply

Right! I forgot about the recursive flag. Anyway, I'm glad to hear that it fixed your problem :)

Reply
Steve-D Avatar
Steve-D Avatar Steve-D | posted 1 year ago

Hi

When I run compose rup on my main machine (iMac) I get the following message.

The "symfony/flex" plugin (installed globally) was skipped because it requires a Plugin API version ("^1.0") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.

When first getting in to using flex I must have somehow installed it globally. (I can see /usr/bin/flex and /usr/bin/flex++) not sure if these are the files though

Is there a way to remove flex globally and thus the error?

Thank you

Steve

Reply

Hey Steve D.!

Yup - I agree with your assessment! You should be able to remove it by running composer global remove symfony/flex.

Let me know if that does the trick :).

Cheers!

Reply
Kevin-C Avatar
Kevin-C Avatar Kevin-C | posted 1 year ago | edited

Hi,
Great videos, Ryan.
During a composer recipes:update and getting back the following list:
<br /> [0 ] liip/imagine-bundle<br /> [1 ] stof/doctrine-extensions-bundle<br /> [2 ] symfony/apache-pack<br /> [3 ] symfony/flex<br /> [4 ] symfony/monolog-bundle<br /> [5 ] symfony/phpunit-bridge<br /> [6 ] symfony/routing<br /> [7 ] symfony/security-bundle<br /> [8 ] symfony/swiftmailer-bundle<br /> [9 ] symfony/translation<br /> [10] symfony/validator<br /> [11] symfony/web-profiler-bundle<br /> [12] symfony/webpack-encore-bundle<br />
I typed 1 to update stof/doctrine-extensions-bundle
and I get the following error:
`
PHP Fatal error: Uncaught TypeError: Argument 1 passed to Symfony\Flex\Command\UpdateRecipesCommand::getRecipe() must be an instance of Composer\Package\Package, instance of Composer\Package\CompleteAliasPackage given, called in /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php on line 128 and defined in /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php:265
Stack trace:
#0 /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php(128): Symfony\Flex\Command\UpdateRecipesCommand->getRecipe(Object(Composer\Package\CompleteAliasPackage), '6c1ceb662f89970...', '1.2')
#1 phar:///usr/local/bin/composer/vendor/symfony/console/Command/Command.php(245): Symfony\Flex\Command\UpdateRecipesCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 phar:///usr/local/bin/composer/vendor/symfony/console/Application.php(835): Symfony\Component\Console\Command\ in /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php on line 265

Fatal error: Uncaught TypeError: Argument 1 passed to Symfony\Flex\Command\UpdateRecipesCommand::getRecipe() must be an instance of Composer\Package\Package, instance of Composer\Package\CompleteAliasPackage given, called in /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php on line 128 and defined in /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php:265
Stack trace:
#0 /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php(128): Symfony\Flex\Command\UpdateRecipesCommand->getRecipe(Object(Composer\Package\CompleteAliasPackage), '6c1ceb662f89970...', '1.2')
#1 phar:///usr/local/bin/composer/vendor/symfony/console/Command/Command.php(245): Symfony\Flex\Command\UpdateRecipesCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 phar:///usr/local/bin/composer/vendor/symfony/console/Application.php(835): Symfony\Component\Console\Command\ in /private/var/www/www.site.com/vendor/symfony/flex/src/Command/UpdateRecipesCommand.php on line 265
`

composer.json (partial)
`
"require": {

    "php": "^7.1.3",
    "ext-ctype": "*",
    "ext-iconv": "*",
    "behat/transliterator": "~1.2",
    "doctrine/cache": "~1.6",
    "doctrine/collections": "~1.4",
    "doctrine/common": "^3.0",
    "doctrine/data-fixtures": "~1.3",
    "doctrine/dbal": "^2.6",
    "doctrine/doctrine-bundle": "^2.4",
    "doctrine/doctrine-migrations-bundle": "^3.0",
    "doctrine/inflector": "^1.2",
    "doctrine/migrations": "^3.0",
    "doctrine/orm": "^2.9",
    "fig/link-util": "^1.1",
    "gedmo/doctrine-extensions": "^3.1",
    "guzzlehttp/guzzle": "^7.3",
    "incenteev/composer-parameter-handler": "~2.1.1",
    "jms/metadata": "^2.4.0",
    "jms/serializer": "^3.14",
    "jms/serializer-bundle": "^3.10",
    "knplabs/knp-components": "2.4.0",
    "knplabs/knp-paginator-bundle": "dev-master",
    "liip/imagine-bundle": "2.x-dev",
    "monolog/monolog": "^1.22",
    "phpcollection/phpcollection": "0.4.0",
    "ramsey/uuid": "3.8.0",
    "sensio/framework-extra-bundle": "~5.2",
    "stfalcon/tinymce-bundle": "^3.0.0",
    "stof/doctrine-extensions-bundle": "^1.7",
    "symfony/apache-pack": "^1.0",
    "symfony/asset": "5.4.*",
    "symfony/cache": "5.4.*",
    "symfony/config": "5.4.*",
    "symfony/console": "5.4.*",
    "symfony/dependency-injection": "5.4.*",
    "symfony/doctrine-bridge": "5.4.*",
    "symfony/dotenv": "5.4.*",
    "symfony/event-dispatcher": "5.4.*",
    "symfony/expression-language": "5.4.*",
    "symfony/flex": "^1.2",
    "symfony/form": "5.4.*",
    "symfony/framework-bundle": "5.4.*",
    "symfony/http-foundation": "5.4.*",
    "symfony/http-kernel": "5.4.*",
    "symfony/lock": "5.4.*",
    "symfony/mime": "5.4.*",
    "symfony/monolog-bridge": "5.4.*",
    "symfony/monolog-bundle": "^3.3",
    "symfony/options-resolver": "5.4.*",
    "symfony/property-access": "5.4.*",
    "symfony/property-info": "5.4.*",
    "symfony/rate-limiter": "5.4.*",
    "symfony/routing": "5.4.*",
    "symfony/runtime": "5.4.x-dev",
    "symfony/security-bundle": "5.4.*",
    "symfony/security-core": "5.4.*",
    "symfony/security-csrf": "5.4.*",
    "symfony/security-guard": "5.4.*",
    "symfony/security-http": "5.4.*",
    "symfony/serializer": "5.4.*",
    "symfony/string": "5.4.*",
    "symfony/swiftmailer-bundle": "^3.2",
    "symfony/translation": "*",
    "symfony/twig-bridge": "5.4.*",
    "symfony/twig-bundle": "5.4.*",
    "symfony/validator": "5.4.*",
    "symfony/web-link": "4.4.*",
    "symfony/web-profiler-bundle": "5.4.*",
    "symfony/webpack-encore-bundle": "^1.1",
    "symfony/yaml": "*",
    "tattali/mobile-detect-bundle": "2.2.0",
    "twig/twig": "^3.0",
    "vich/uploader-bundle": "^1.18",
    "vwo/vwo-php-sdk": "dev-master"
},

`
It's not just this package, it's also monolog-bundle

Would love your input/suggestions on how to tackle this one.
Thanks,
Kevin

Reply

The rector.php file generated is completely different from the one in the tutorial, and also the rector github docs. I guess they updated rector in the meantime?

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