Upgrading to Symfony 5.0
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeWe've done it! We fixed all the deprecations in our app... except for the doctrine/persistence
stuff, which we don't need to worry about because we're not upgrading that library. That means... we are ready for Symfony5!
Changing composer.json for Symfony 5.0
How... do we actually upgrade? We already know: it's the exact same process we used to upgrade from 4.3 to 4.4.
Open up composer.json
. Our goal is to update all of these symfony/
libraries to 5.0:
{ | |
// ... lines 2 - 3 | |
"require": { | |
// ... lines 5 - 24 | |
"symfony/asset": "4.4.*", | |
"symfony/console": "4.4.*", | |
"symfony/dotenv": "4.4.*", | |
"symfony/flex": "^1.0", | |
"symfony/form": "4.4.*", | |
"symfony/framework-bundle": "4.4.*", | |
"symfony/mailer": "4.4.*", | |
"symfony/messenger": "4.4.*", | |
"symfony/monolog-bundle": "^3.5", | |
"symfony/security-bundle": "4.4.*", | |
"symfony/sendgrid-mailer": "4.4.*", | |
"symfony/serializer-pack": "^1.0", | |
"symfony/twig-bundle": "4.4.*", | |
"symfony/twig-pack": "^1.0", | |
"symfony/validator": "4.4.*", | |
"symfony/webpack-encore-bundle": "^1.4", | |
"symfony/yaml": "4.4.*", | |
// ... lines 42 - 44 | |
}, | |
"require-dev": { | |
// ... lines 47 - 48 | |
"symfony/browser-kit": "4.4.*", | |
"symfony/debug-bundle": "4.4.*", | |
"symfony/maker-bundle": "^1.0", | |
"symfony/phpunit-bridge": "4.4.*", | |
"symfony/profiler-pack": "^1.0", | |
"symfony/var-dumper": "4.4.*" | |
}, | |
// ... lines 56 - 103 | |
} |
Well, not quite all of them - a few are not part of the main Symfony library, like monolog-bundle
. But basically, everything that has 4.4.*
now needs to be 5.0.*
.
We also need to update one more thing: the extra.symfony.require
value:
{ | |
// ... lines 2 - 96 | |
"extra": { | |
"symfony": { | |
// ... lines 99 - 100 | |
"require": "4.4.*" | |
} | |
} | |
} |
This is primarily a performance optimization that helps Composer filter out extra Symfony versions when it's trying to resolve packages. This also needs to change to 5.0.*
.
Let's... do it all at once: Find 4.4.*
, replace it with 5.0.*
and hit "Replace all":
{ | |
// ... lines 2 - 3 | |
"require": { | |
// ... lines 5 - 24 | |
"symfony/asset": "5.0.*", | |
"symfony/console": "5.0.*", | |
"symfony/dotenv": "5.0.*", | |
// ... line 28 | |
"symfony/form": "5.0.*", | |
"symfony/framework-bundle": "5.0.*", | |
"symfony/mailer": "5.0.*", | |
"symfony/messenger": "5.0.*", | |
// ... line 33 | |
"symfony/security-bundle": "5.0.*", | |
"symfony/sendgrid-mailer": "5.0.*", | |
// ... line 36 | |
"symfony/twig-bundle": "5.0.*", | |
// ... line 38 | |
"symfony/validator": "5.0.*", | |
// ... line 40 | |
"symfony/yaml": "5.0.*", | |
// ... lines 42 - 44 | |
}, | |
"require-dev": { | |
// ... lines 47 - 48 | |
"symfony/browser-kit": "5.0.*", | |
"symfony/debug-bundle": "5.0.*", | |
// ... line 51 | |
"symfony/phpunit-bridge": "5.0.*", | |
// ... line 53 | |
"symfony/var-dumper": "5.0.*" | |
}, | |
// ... lines 56 - 96 | |
"extra": { | |
"symfony": { | |
// ... lines 99 - 100 | |
"require": "5.0.*" | |
} | |
} | |
} |
And then... make sure that this didn't accidentally replace any non-Symfony packages that may have had the same version.... looks good.
Updating Symfony Packages in Composer
We're ready! At your terminal... I'll hit Ctrl
+C
to stop the log tail.... and run the same command we used when upgrading from Symfony 4.3 to 4.4:
composer update "symfony/*"
That's it! It's that easy! We're done! Kidding - it's never that easy: you will almost definitely get some dependency errors. Probably... several. Ah, here's our first.
Composer: Many Packages Need to Update
These errors are always a little hard to read. This says that the current version of doctrine/orm
in our project is not compatible with Symfony 5... which means that it also needs to be updated. Specifically we need a newer version that's compatible with symfony/console
version 5.
And... it's possible that there is not yet a release of doctrine/orm
that supports Symfony 5 - we hit that problem earlier with StofDoctrineExtensionsBundle. But... let's blindly try it! Add doctrine/orm
to our update list and try again:
composer update "symfony/*" doctrine/orm
And... another error. Actually, the same error but this time for knplabs/knp-markdown-bundle
. We don't know if this bundle has a Symfony5-compatible release either... and even if it does... it might require a major version upgrade. But the easiest thing to do is add it to our list and hope for the best. Try it:
composer update "symfony/*" doctrine/orm knplabs/knp-markdown-bundle
So... this is going to happen several more times - this is the same error for knplabs/knp-snappy-bundle
. Little-by-little, we're discovering all the packages that we need to upgrade to be compatible with Symfony 5. Instead of doing this one-by-one, you can also choose the easy route: just run composer update
with no arguments and allow Composer to update everything.
I prefer to upgrade more cautiously than that... but it's not a bad option. After all, our Composer version constraints don't allow any major version upgrades: so running composer update
still won't allow any new major package versions unless you tweaked your composer.json
file.
Let's keep going with my cowardly, I mean, cautious way: copy the package name and add it to the update command:
composer update "symfony/*" \
doctrine/orm \
knplabs/knp-markdown-bundle \
knplabs/knp-snappy-bundle
Let's keep trying and... I'll fast-forward through a few more of these: this is for liip/imagine-bundle
- add that to the update command - then oneup/flysystem-bundle
... and now sensio/framework-extra-bundle
: add that to our very-long update command:
composer update "symfony/*" \
doctrine/orm \
knplabs/knp-markdown-bundle \
knplabs/knp-snappy-bundle \
liip/imagine-bundle \
oneup/flysystem-bundle \
sensio/framework-extra-bundle
Updating --with-dependencies
Hmm, but this next error looks a bit different: it's something about doctrine/orm
and doctrine/instantiator
. If you look closely, this says that in order to get Symfony 5 support, we need doctrine/orm
version 2.7, but version 2.7 requires doctrine/instantiator
1.3... and our project is currently locked at version 1.2.
Our app doesn't require doctrine/instantiator
directly: it's a dependency of doctrine/orm
. We saw this earlier when we were updating doctrine-migrations-bundle
and we also needed to allow its dependency - doctrine/migrations
to update.
We allow that by adding --with-dependencies
to the update command:
composer update "symfony/*" \
doctrine/orm \
knplabs/knp-markdown-bundle \
knplabs/knp-snappy-bundle \
liip/imagine-bundle \
oneup/flysystem-bundle \
sensio/framework-extra-bundle \
--with-dependencies
Updating our PHP Version
And... this gets us to our next error. Oh, interesting! Apparently nexylan/slack-bundle
version 2.2.1 requires PHP 7.3! We saw a similar error earlier, which caused us to decide that our production app would now need to at least run PHP 7.2. We enforced that by adding a config.platform.php
setting in composer.json
to 7.2.5. This says:
Yo Composer! Pretend I'm using PHP 7.2.5 and don't let me use any packages that require a higher version of PHP.
So... hmm. Apparently the version of nexylan/slack-bundle
that supports Symfony 5 requires PHP 7.3. Basically... unless we want to stop using that bundle, it means that we need to start using PHP 7.3 as well.
Fortunately, I'm already using PHP 7.3 locally: so I just need to change my config.platform.php
setting to 7.3 and also makes sure that we have 7.3 on production.
Inside composer.json
, search for platform
: there it is. Use 7.3.0. And, even though it doesn't affect anything in a project, also change the version under the require
key:
{ | |
// ... lines 2 - 3 | |
"require": { | |
"php": "^7.3.0", | |
// ... lines 6 - 44 | |
}, | |
// ... lines 46 - 55 | |
"config": { | |
// ... lines 57 - 60 | |
"platform": { | |
"php": "7.3.0" | |
} | |
}, | |
// ... lines 65 - 103 | |
} |
Ok, now try to update:
composer update "symfony/*" \
doctrine/orm \
knplabs/knp-markdown-bundle \
knplabs/knp-snappy-bundle \
liip/imagine-bundle \
oneup/flysystem-bundle \
sensio/framework-extra-bundle \
--with-dependencies
Bah! I should've seen that coming: it's still complaining about nexylan/slack-bundle
: it's reminding us that we need to also allow that bundle to update. Add it to our list:
composer update "symfony/*" \
doctrine/orm \
knplabs/knp-markdown-bundle \
knplabs/knp-snappy-bundle \
liip/imagine-bundle \
oneup/flysystem-bundle \
sensio/framework-extra-bundle \
nexylan/slack-bundle \
--with-dependencies
And try it. Surprise! Another package needs to be update. I swear we're almost done. Add that to our gigantic update command:
Tip
We need this for our course CI, just ignore this note and follow the tutorial without executing these commands :)
sed -i 's/"4.4.*"/"5.0.*"/g' ./composer.json
sed -i 's/public function getExtendedType()/public static function getExtendedTypes(): iterable/g' ./src/Form/TypeExtension/TextareaSizeExtension.php
sed -i 's/TextareaType::class/\[TextareaType::class\]/g' ./src/Form/TypeExtension/TextareaSizeExtension.php
sed -i 's/extends Controller/extends AbstractController/g' ./src/Controller/CommentAdminController.php
sed -i 's/use Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller/use Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController/g' ./src/Controller/CommentAdminController.php
sed -i 's/use Doctrine\\Common\\Persistence\\ObjectManager/use Doctrine\\Persistence\\ObjectManager/g' ./src/DataFixtures/ArticleFixtures.php
sed -i 's/use Doctrine\\Common\\Persistence\\ObjectManager/use Doctrine\\Persistence\\ObjectManager/g' ./src/DataFixtures/BaseFixture.php
sed -i 's/use Doctrine\\Common\\Persistence\\ObjectManager/use Doctrine\\Persistence\\ObjectManager/g' ./src/DataFixtures/CommentFixture.php
sed -i 's/use Doctrine\\Common\\Persistence\\ObjectManager/use Doctrine\\Persistence\\ObjectManager/g' ./src/DataFixtures/TagFixture.php
sed -i 's/use Doctrine\\Common\\Persistence\\ObjectManager/use Doctrine\\Persistence\\ObjectManager/g' ./src/DataFixtures/UserFixture.php
echo "delete duplicated file" && rm config/routes/dev/twig.yaml
composer update "symfony/*" \
doctrine/orm \
knplabs/knp-markdown-bundle \
knplabs/knp-snappy-bundle \
liip/imagine-bundle \
oneup/flysystem-bundle \
sensio/framework-extra-bundle \
nexylan/slack-bundle \
knplabs/knp-time-bundle \
easycorp/easy-log-handler \
knplabs/knp-paginator-bundle \
stof/doctrine-extensions-bundle \
doctrine/doctrine-bundle \
doctrine/doctrine-fixtures-bundle \
doctrine/doctrine-migrations-bundle \
twig/cssinliner-extra \
--with-dependencies
Other than Symfony: (Mostly) Only Safe Minor Upgrades
And... whaaaat? It's working! It's upgrading a ton of packages, including the Symfony stuff to 5.0.2. And, because we didn't change any other version constraints inside composer.json
, we know that all of these upgrades are just minor version upgrades at best. For example, nexylan/slack-bundle
went from 2.1 to 2.2. Even if there were a new version 3 of this bundle, we know that it wouldn't upgrade to it because its version constraint is ^2.1
, which allows 2.1 or higher, but not 3:
{ | |
// ... lines 2 - 3 | |
"require": { | |
// ... lines 5 - 20 | |
"nexylan/slack-bundle": "^2.1", | |
// ... lines 22 - 44 | |
}, | |
// ... lines 46 - 103 | |
} |
Well, that's not completely true: check out nexylan/slack
: it went from version 2.3 to 3: that is a major upgrade. That's because this is one of those transitive dependencies: this package isn't in our composer.json
, it only lives in our project because nexylan/slack-bundle
requires it. So unless we're using its code directly - which is possible, but less likely - the major upgrade won't affect us. If you're worried, check its CHANGELOG.
Ok, so we are now on Symfony 5. Woo! The little icon on the bottom right of the web debug toolbar shows 5.0.2.
Next, let's celebrate by trying out some new features! We'll start by talking about Symfony's new "secrets management".
I can't use the symfony/* syntax, it tells me
I can follow along just fine with running the whole composer update, just curious why it doesn't work for me when it works for you =)