gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
At your terminal, run:
composer recipes
As you probably know, whenever we install a new package, that package may come with a recipe that does things like add configuration files, modify certain files like .env
, or add other files. Over time, Symfony makes updates to these recipes. Sometimes these are minor... like the addition of a comment in a config file. But other times, they're bigger, like renaming config keys to match changes in Symfony itself. And while you don't have to update your recipes, it's a great way to keep your app feeling like a standard Symfony app. It's also a free way to update deprecated code!
Until recently, updating recipes was a pain. If you're not familiar, just check our "Upgrade to Symfony 5" tutorial! Yikes. But no more! Starting with Symfony Flex 1.18 or 2.1, Composer has a proper recipes:update
command. It literally patches your files to the latest version... and it's awesome. Let's try it!
Run:
composer recipes:update
Oh! Before we run this, it tells us to commit everything that we've been working on. Great idea! I'll say that we are:
upgrading some code to Symfony 5.4 with Rector
git add .
git commit -m "upgrading some code to Symfony 5.4 with Rector"
Perfect! Try the recipes:update
command again. The reason it wants our working copy to be clean is because it's about to patch some files... which might involve conflicts.
Let's start with symfony/framework-bundle
, because this is the big one. The most important files in our project come from this recipe. I'll hit 4
, clear the screen, and go!
Behind the scenes, this checks to see what the recipe looked like when we originally installed it, compares it to what the recipe looks like now, and generates a diff that it then applies to our project. In some cases, like this one, that can cause some conflicts, which is pretty cool. The best part might be that it generates a changelog containing all the pull requests that contributed to these updates. If you need to figure out why something changed, this will be your friend.
Oh, but creating the changelog requires making a bunch of API calls to GitHub. So it's possible that composer will ask you for a personal access token, like it just did for me. In some rare cases with a giant recipe like framework-bundle
, if your recipe is really, really old, you might get this message even if you have given an access token to Composer. If that happens, just wait for 1 minute... then re-enter your access token. Congratulations, you just hit GitHub's per-minute API limit.
Anyways, there's the CHANGELOG. It's not usually that long, but this recipe is the most important and... well... it was horribly out-of-date. Oh, and if you have a trendy terminal like me - this is iTerm - you can click these links to jump directly into the pull request, which will live at https://github.com/symfony/recipes.
Alright, let's walk through the changes this made. This is the biggest and most important recipe, so I want to cover everything.
Since I've already done my homework, I'll clear the changelog and run:
git status
Woh. It made a bunch of changes, including three conflicts. Fun! Let's go through those first. Move over and start inside .env
. Let's see: apparently the recipe removed these #TRUSTED_PROXIES
and #TRUSTED_HOSTS
lines.
... 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 |
Both of these are now set in a config file. And while you could still set an environment variable and reference it from that config file, the recipe no longer ships with these comments. I'm not sure why this caused a conflict, but let's delete them.
The next conflict is up in config/services.yaml
. This one is pretty simple. This is our config and below, the new config. The recipe removed the App\Controller\
entry. This... was never needed unless you make super-fancy controllers that do not extend AbstractController
. It was removed from the recipe for simplicity. It also looks like the updated recipe reformats the exclude
onto multiple lines, which is nice. So let's take their version entirely.
... lines 1 - 8 | |
services: | |
... lines 10 - 18 | |
App\: | |
resource: '../src/' | |
exclude: | |
- '../src/DependencyInjection/' | |
- '../src/Entity/' | |
- '../src/Kernel.php' | |
... lines 25 - 30 |
The final conflict is in src/Kernel.php
... where you can see that our side has a bunch of code in it... and their side has nothing.
Remember how I mentioned that configureRoutes()
was moved into MicroKernelTrait
? Well it turns out that all of these methods were moved into MicroKernelTrait
. So unless you have some custom logic - which is pretty rare - you can delete everything.
... lines 1 - 7 | |
class Kernel extends BaseKernel | |
{ | |
use MicroKernelTrait; | |
} |
Ok, back at the terminal, let's add those three files:
git add .env config/services.yaml src/Kernel.php
And then run
git status
to see what else the recipe update did.
Interesting. It deleted config/bootstrap.php
and modified public/index.php
. Those are related. Look at the diff of index.php
:
git diff --cached public/index.php
This file used to require config/bootstrap.php
. And that file's job was to read and set up all the environment variables:
git diff --cached config/
Let's go check out the new public/index.php
. Here it is. Now this requires some vendor/autoload_runtime.php
. And the file is much shorter than before. What we're seeing is Symfony's new Runtime component in action.
... 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']); | |
}; |
You can check out its introduction blog post to learn more about it.
Basically, the job of booting up Symfony and loading all of the environment variables was extracted into the runtime component. But... we don't actually have that component installed yet... which is why, if we try to refresh the page, we're gonna have a bad time:
Failed to open
autoload_runtime.php
.
To fix this, head over to your terminal and run:
composer require symfony/runtime
This package includes a Composer plugin... so it's going to ask us if we trust it. Say "yes". Then it installs... and promptly explodes when it tries to clear the cache! Ignore that for now: we'll fix it in a few minutes. It involves updating another recipe.
But if we try our site... it works!
Ok, we're almost done! Back at the terminal, let's see what else changed:
git status
Notice that it deleted config/packages/test/framework.yaml
, but modified config/packages/framework.yaml
. This is probably the most common change that you'll see when you update your recipes today.
Open config/packages/framework.yaml
. At the bottom... there's a new when@test
section.
... lines 1 - 19 | |
when@test: | |
framework: | |
test: true | |
session: | |
storage_factory_id: session.storage.factory.mock_file |
Starting in Symfony 5.3, you can now add environment-specific config using this syntax. This configuration used to live inside of config/packages/test/framework.yaml
. But for simplicity, the recipe deleted that file and just moved that config to the bottom of this file.
Back at the terminal, diff that file... it's hiding two other changes:
git diff --cached config/packages/framework.yaml
The recipe also changed http_method_override
to false
. That disables, by default, a feature that you probably weren't using anyways. It also set storage_factory_id
to session.storage.factory.native
. This has to do with how your session is stored. Internally, the key changed from storage_id
to storage_factory_id
, and it should now be configured.
Back at the terminal, let's look at the final changes:
git status
Speaking of environment-specific config, you can do that same trick with routing files. See how it deleted config/routes/dev/framework.yaml
, but added config/routes/framework.yaml
? If we open up config/routes/framework.yaml
, yup! It has when@dev
and it imports the routes that allow us to test our error pages.
when@dev: | |
_errors: | |
resource: '@FrameworkBundle/Resources/config/routing/errors.xml' | |
prefix: /_error |
This is yet another example of the recipe moving configuration out of the environment directory and into the main configuration file... just for simplicity.
Finally, the recipe added a config/preload.php
file. This one is pretty simple, and it leverages PHP's preloading functionality.
... 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'; | |
} |
Essentially, on production, if you point your php.ini
, opcache.preload
at this file, you'll get a free performance boost! It's that simple. Well... mostly that simple. The only other thing you need to do is restart your web server on every deploy... or PHP-FPM if you're using that. We leverage this at SymfonyCasts for a little extra performance boost.
And... phew! The biggest recipe update is done. So let's add everything and commit. Because next, more recipe updates! But with FrameworkBundle behind us, the rest will be easier and faster.
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
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
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!
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
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!
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
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!
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.
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
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!
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
`
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
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!
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!
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 ...
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!
// 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
}
}
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? :)