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 SubscribeWhile we're doing all of these major upgrades, we might as well make sure everything is upgraded. When we run
composer outdated
it gives us a list of all of the things we still need to update. As I mentioned, we're going to ignore knplabs/knp-markdown-bundle
. But if you have that in a real project, refactor it to use twig/markdown-extra
.
What I'm interested in is doctrine/dbal
, which has a new major version we can upgrade to. But... this begs the question: Why didn't this upgrade automatically when we did composer up
? Run
composer why-not doctrine/dbal 3
to find out what is preventing us from upgrading to version 3 of this package. Of course! We're holding it back. It says that our project requires doctrine/dbal (^2.13)
. Whoops...
Head over to composer.json
and... sure enough: ^2.13
. Change that to the latest ^3.3
. Moment of truth. Run
{ | |
... lines 2 - 5 | |
"require": { | |
... lines 7 - 12 | |
"doctrine/dbal": "^3.3", | |
... lines 14 - 47 | |
}, | |
... lines 49 - 111 | |
} |
composer up
And... woo! It updated! Do
composer outdated
again. Alright! Other than knp-markdown-bundle
, this is empty.
We did just perform a major version upgrade. So the new version does contain backwards-compatibility breaks. You'll want to look into the library's CHANGELOG a bit deeper to make sure you're not affected. But, I can tell you that most of the changes relate to if you're using doctrine/dbal
directly, for example to make queries direclty in DBAL. Typically, when you're working with the Doctrine ORM & entities - even if you're making custom queries - you're not doing that. On our site... we seem to be just fine.
Now that we've upgraded from Symfony 5.4 to 6.0, it's possible that some recipes have new versions we can update to. Run:
composer recipes:update
Oh, whoops! I need to commit my changes:
git commit -m 'upgrading doctrine/dbal from 2 to 3'
Perfect! Now run
composer recipes:update
and... cool! There are two. Start with symfony/routing
. And... we have conflicts! Run:
git status
The problem is in config/routes.yaml
. Let's check that out. Ok, so previously, I commented out this route.
#index: | |
# path: / | |
# controller: App\Controller\QuestionController::homepage |
The recipe update added the controllers
and kernel
imports. Let's keep their changes. These are actually importing our route annotations or attributes from the ../src/Controller
directory... and also allowing you to add routes and controllers directly to your Kernel.php
file.
controllers: | |
resource: ../src/Controller/ | |
type: annotation | |
kernel: | |
resource: ../src/Kernel.php | |
type: annotation |
It says type: annotation
... but that importer is able to load annotations or PHP 8 attributes. One of the nice things about Symfony 6 is that you can load route attributes without any external library. It's just... part of the routing system. For that reason, these route imports were added to our main config/routes.yaml
file when we install symfony/routing
.
Go ahead and commit that. This change will make even more sense after we upgrade the final recipe.
Run
composer recipes:update
again and, this time, let's update the doctrine/annotations
recipe. Interesting. It deleted config/routes/annotations.yaml
. If you look closely, that actually contained the two lines that were added by the previous recipe update!
Here's the deal. Back before PHP 8 - when we only had annotation routes - the doctrine/annotations
library was required to import route annotations. So we only gave you these imports lines once you installed that library.
But now that we use attribute routes, that's no longer true! We do not need the doctrine/annotations
package anymore. For that reason, we now immediately give you these attribute route import lines as soon as you install the routing component.
If we look over here, nothing changes on our front end. All of our routes still work.
Finally, now that we're on Symfony 6, we can remove some code that was only needed to keep things working on Symfony 5. There's not much of this that I know of... the only I can think of is in User.php
.
As I mentioned earlier, in Symfony 6, UserInterface
... I'll click into that... renamed getUsername()
to getUserIdentifier()
. In Symfony 5.4, to remove the deprecations but keep your code working, we need to have both of these methods. But as soon as you upgrade to Symfony 6, you don't need the old one anymore! Just make sure that you're not calling this directly from your code.
... lines 1 - 14 | |
class User implements UserInterface, PasswordAuthenticatedUserInterface | |
{ | |
... lines 17 - 79 | |
/** | |
* A visual identifier that represents this user. | |
* | |
* @see UserInterface | |
*/ | |
public function getUsername(): string | |
{ | |
return (string) $this->email; | |
} | |
... lines 89 - 221 | |
} |
Another spot down here... is getSalt()
. This is an old method related to how you hash passwords, and it's no longer needed in Symfony 6. Modern password hashing algorithms take care of the salting themselves, so this is completely useless.
And... that's it team! We're done! Our Symfony 6 app is fully upgraded! We upgraded recipes, updated to PHP 8 code, are using PHP 8 attributes instead of annotations and more. That was a ton of stuff... and we just modernized our codebase big time.
I think this deserves a whole pizza to celebrate. Then come right back, because I want to take a quick test drive of a few more new features that we haven't talked about. Those are next.
"Houston: no signs of life"
Start the conversation!
// 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
}
}