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!

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