Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Recipe Upgrade: symfony/console & bootstrap.php

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.

The first recipe I want to update is symfony/console. Let's get some more info about it:

composer recipes symfony/console

Just like before, it shows us some links: a link to what the recipe looked like at the moment we installed it - I'll paste that into my browser - and also a version of what the recipe looks like right now. Let's open up that one too.

Recipe Organization & History

We're not going to always study the history of a recipe like this, but I need to show you something. Because of the way that recipes are organized, if you want see what changed in a recipe since you installed it, it's not always as easy as looking at the history.

This is what the recipe looks like today. Click to look at the commit history. You might think:

Okay, I'll just go back and see what commits have been made to this recipe since my version.

That's a great idea, because sometimes knowing why something changed can be a huge help. But... the installed version of my recipe lives in a symfony/console/3.3/ directory. The new one lives in symfony/console/4.4/.

Let's look at this entire symfony/console directory. Oh, and make sure that you're looking at the master branch - the latest commits. Each recipe is allowed to have multiple versions. If you installed symfony/console version 3.3, Flex would install the 3.3 recipe. If you installed 4.2, you would get the 4.2 recipe. What if you installed symfony/console 4.1? You would get the 3.3 recipe. A new directory is created only when a recipe needs to be updated to show off a feature that's only available in a newer version.

So, it's kind of a strange versioning mechanism. When we installed this recipe, we installed the 3.3 version. Updating it would install the 4.4 version. So if you want to see the full history... it's tricky: you kind of need to look at the history of what commits have been made to the 4.4 branch... and also maybe the history of what's been done to the 4.2 branch.... and also maybe the commit history for the 3.3 branch.

But, it's not as bad as it sounds - I'm trying to deliver the bad news first. Most of the time, the reason a file was updated in a recipe will be pretty obvious. And when it's not, with a little digging, we can find the reason.

Let's update a Recipe

Okay, so how do we actually upgrade a recipe to the latest version? You can see the answer down here: composer recipes:install symfony/console --force -v.

But, it's not really a smart "update" system. That command tells Flex to completely re-install the symfony/console recipe using the latest version. Try it:

composer recipes:install symfony/console --force -v


Starting with symfony 5.1, the config/bootstrap.php is not used anymore. And so, you won't see it added when upgrading the recipe. You can safely delete this file: updates to your bin/console file now handle that file's job.

Nice! Thanks to the -v flag, it tells us what files it worked on. It says:

Created bin/console
Created config/bootstrap.php

Well, really, it modified those files... but at least in the version of Flex I'm using, it always says "created".

Let's see how things look. Run:

git status

Cool! 3 changed files. Just like with the MonologBundle recipe, we need to add these changes carefully: if we had any custom code in the files, the update process just replaced it. Run:

git add -p

The bin/console changes

The first file is bin/console... and it's a namespace change from Debug to ErrorHandler. This is updating our code to use a new ErrorHandler component - some features of the Debug component were moved there. So that's a good change.

It also... I don't know, added some if statement that prints a warning... it looks like it's just making sure we don't try to run this from inside a web server. Enter "y" to add both changes.

Investigating a Change

Next, woh! It removed a huge block of code from the bottom and tweaked an if statement further up. These changes are on config/bootstrap.php.

This... looks like some low-level, edge-case normalization of environment variables. So probably we want this. But let's pretend we don't know: we want to find out why this change was made.

How? By doing some digging! Go back to symfony/recipes/console. Start by looking in the 4.4/ directory - the version we're installing. Find config/bootstrap.php.

Wait... see the config/ directory? What does that little arrow mean? It means that this is actually a symbolic link to another directory: the 4.4/config directory is identical to 4.2/config.

Ok, let's go look there! Head into the 4.2/ directory, then config/. Woh! Another arrow! This time the bootstrap.php file is a symlink - pointing to, wow! A totally different recipe - a bootstrap.php file in framework-bundle.

The bootstrap.php file is the most complex file in the recipe system and it's shared across several recipes. Yep, I'm showing you the ugliest case.

Let's go find that: symfony/framework-bundle/4.2/config/bootstrap.php. Here is the file. To find the change, use the "blame" feature. Ok, the block of code we're looking at - lines 9 through 12 - have two different commits. Let's look at just one of them:

Allow correct environment to be loaded when .env.local.php exists

And we can even click to see the pull request: #647 if you want really dive into the details. In this case, the change fixes a bug if you use the .env.php.local file.

But, really, config/bootstrap.php is a low-level file that should almost always be identical in every project. So unless you're doing something super advanced, you will probably want to accept all of these changes.

This big removal of code? That was because in an earlier version of this recipe, your project may or may not have had this loadEnv() method on DotEnv: it was added in Symfony 4.2. If your app did not have that method, it added a bunch of code to "imitate" its behavior. We don't need that anymore. Thank you recipe update!

The last change is for the symfony.lock file. We don't even need to look at this: always accept these changes. This marks the recipe as updated and sometimes saves extra debugging info that might be useful later.

That may have seemed like a small step. But other than trying to figure out the reasons a file changed, this was a home run! We were able to update two low-level files, which will help make sure our app continues to work like we expect.

Go ahead and commit these changes. Then let's keep going. Next, we'll update the biggest and most important recipe: the one for symfony/framework-bundle.

Leave a comment!

Login or Register to join the conversation
Kieran B. Avatar
Kieran B. Avatar Kieran B. | posted 1 year ago

is config/bootstrap.php no longer part of a recipe?


Hey Kieran B.

Yes it's so. It was dropped in Symfony 5.1 IIRC


Kieran B. Avatar

Thanks Vladimir,

When updating recipes, does flex not remove files that are no longer used. Seems that the bootstrap file I had integrated with an older version of dotenv. The site worked file but when I installed phpunit then it would check to see if the bootstrap file was there and try to include it causing an issue. Removing the file manually worked but it did make me wonder what other cleanup I need to do.


Yeah that's a bummer! I also faced this issue when updated some projects. Honestly I don't know good approach to find such cases, I think the only way is to check recipes while updating stuff.


Polychronis Avatar
Polychronis Avatar Polychronis | posted 2 years ago | edited

Trying to perform a "minor" version upgrade <b>[ 5.2 to 5.3 ]</b>
on a fresh/clean symfony 5.2 project
(i.e. `composer create-project symfony/website-skeleton:"5.2.*" s5test` )

Then i just add a home page for testing purposes (https://symfony.com/doc/current/page_creation.html)

In composer.json: i change:
"symfony/...": "5.2." to "symfony/...": "5.3."
"symfony/...": "^5.2 to "symfony/...": "^5.3"

[composer update "symfony/*" --with-all-dependencies] runs ok

To complete the upgrade i need to install 6 recipes

recipes: [symfony/routing, symfony/security-bundle, symfony/translation, symfony/twig-bundle] install ok...

<i>But with these 2 recipes:</i>

<b>- symfony/console: </b>
after I install this one, when i run composer update:
i get: Executing script cache:clear [KO] [KO] Script cache:clear returned with error code 255 !! Script @auto-scripts was called via post-update-cmd
and php bin/console cache:clear does not do anything along with any other console cmd

<b>- symfony/framework-bundle:</b>
after I install this one i get an empty page on my browser
no debug toolbar and nothing at var/log/dev.log

<b>To sum it up:</b> after installing these 2 recipes:

  • console terminal does not work anymore
  • homepage does not display anything.

anyone had this issue ? any hints?

Polychronis Avatar

installing runtime
`composer require symfony/runtime`
solves this issue...

for some reason at my setup the error did not hint a solution
while at an other setup it did.... found it at stackoverflow after posting a question there...


Hey Polychronis,

Good catch on that "symfony/runtime". Unfortunately, it's difficult to say what may goes wrong without seeing the exact errors. For the future, I'd recommend you too check logs - they may hind with some problems. And yeah, another way to search on StackOverflow is also a good idea, well done :)


1 Reply
Trafficmanagertech Avatar
Trafficmanagertech Avatar Trafficmanagertech | posted 3 years ago

Doing this moved my .env.dist to .env and created the bootstrap.php + some additional .env.local and .env.test...
I really do not want to use .env files, I have for example 10 clients on the same machine, each of them has different db credentials, so the parameters should be different... The old good parameters.yaml, untracked from git, was perfect... is it possible to use symfony 5 without the dotenv component?

Ad F. Avatar

you should open an issue on github :)

Trafficmanagertech Avatar
Trafficmanagertech Avatar Trafficmanagertech | Trafficmanagertech | posted 3 years ago

It seems I can't because the bin/console now has hardcoded references to dotenv... I'll leave it even if the variables inside the .env are not used anywhere


Hey Trafficmanagertech ,

It still should be possible to use old-known parameters.yaml instead of env vars in Symfony. I'm not sure 100% if it works out of the box now (I think it should), but you may need to modify a few files in your project that link to the .env files. Also, for clarity, if you don't use env vars at all - I'd suggest to remove .env files completely from your project... or at least remove all env vars in those files. Unfortunately, if you use Symfony Flex - it will try to modify .env files on composer commands. If you want to continue using Symfony Flex - you would probably need to manually revert .env changes after each Composer installation.

About bin/console - you should be able to specify in what env you want to run the Symfony command with "--env" option, e.g:
"$ bin/console --env=prod"

Anyway, using parameters.yaml instead is still should be possible. Though, I'd recommend you to get used to .env files instead. Mostly, it's the same parameters but more flexible. I hope this helps!


1 Reply
Trafficmanagertech Avatar
Trafficmanagertech Avatar Trafficmanagertech | Victor | posted 3 years ago

Hi, thank you very much,
yes we are already phasing out the parameters.yaml and moving all the settings to a `settings` table in the db, the only one setting that will remain will be the db connection string and you're right, it could be moved to the .env... (ultimately we want to move also that to the db, using a different db_name depending on the HTTP_HOST... we have a SaaS platform with up to 50 clients on one machine and it would be much easier)


Hey Trafficmanagertech ,

Glad to hear you found a workaround! Yeah, it's up to you, but probably leaving as is using .env for DB connection is the simplest solution.


1 Reply

Hey Trafficmanagertech

That's a good question. If you don't want to manage your env vars in the Symfony way, you can totally do it. The first option would be to do what you did, just ignore the .env files and keep going. Or, you can modify the config/bootstrap.php to stop trying to use the DotEnv component and implement your own logic to initialize your env vars. Does it makes sense to you?


1 Reply
Default user avatar
Default user avatar Nicholas Wright | posted 3 years ago | edited

I fell at the first hurdle with composer recipes symfony/console throwing:
[Symfony\Component\Console\Exception\CommandNotFoundException] <br />Command "recipes" is not defined.

Running composer update fixed it.


Hey Nicholas,

Please, make sure you have the latest version of Composer. If not - try to upgrade to the latest. And if you still don't see the command - upgrade "symfony/flex" to the latest version as well. Let me know if after these steps you still don't have "recipes" command :)


Default user avatar
Default user avatar didier2l | posted 3 years ago | edited

Hey Ryan !
there's a little error here :
composer recipes install symfony/console --force -v
It's missing the : between composer & recipes.

By the way, thanks for your amazing work on symfonycasts :)


Hey Didier2l,

Thank you for reporting it! I just merged PR that fixes it: https://github.com/knpunive... . So now it's fixed :)


Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": "^7.3.0",
        "ext-iconv": "*",
        "antishov/doctrine-extensions-bundle": "^1.4", // v1.4.2
        "aws/aws-sdk-php": "^3.87", // 3.110.11
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/doctrine-bundle": "^2.0", // 2.0.6
        "doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // 2.1.2
        "doctrine/orm": "^2.5.11", // v2.7.2
        "doctrine/persistence": "^1.3.7", // 1.3.8
        "easycorp/easy-log-handler": "^1.0", // v1.0.9
        "http-interop/http-factory-guzzle": "^1.0", // 1.0.0
        "knplabs/knp-markdown-bundle": "^1.7", // 1.8.1
        "knplabs/knp-paginator-bundle": "^5.0", // v5.0.0
        "knplabs/knp-snappy-bundle": "^1.6", // v1.7.0
        "knplabs/knp-time-bundle": "^1.8", // v1.11.0
        "league/flysystem-aws-s3-v3": "^1.0", // 1.0.23
        "league/flysystem-cached-adapter": "^1.0", // 1.0.9
        "league/html-to-markdown": "^4.8", // 4.8.2
        "liip/imagine-bundle": "^2.1", // 2.3.0
        "nexylan/slack-bundle": "^2.1", // v2.2.1
        "oneup/flysystem-bundle": "^3.0", // 3.3.0
        "php-http/guzzle6-adapter": "^2.0", // v2.0.1
        "sensio/framework-extra-bundle": "^5.1", // v5.5.3
        "symfony/asset": "5.0.*", // v5.0.2
        "symfony/console": "5.0.*", // v5.0.2
        "symfony/dotenv": "5.0.*", // v5.0.2
        "symfony/flex": "^1.0", // v1.17.6
        "symfony/form": "5.0.*", // v5.0.2
        "symfony/framework-bundle": "5.0.*", // v5.0.2
        "symfony/mailer": "5.0.*", // v5.0.2
        "symfony/messenger": "5.0.*", // v5.0.2
        "symfony/monolog-bundle": "^3.5", // v3.5.0
        "symfony/security-bundle": "5.0.*", // v5.0.2
        "symfony/sendgrid-mailer": "5.0.*", // v5.0.2
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "5.0.*", // v5.0.2
        "symfony/twig-pack": "^1.0", // v1.0.0
        "symfony/validator": "5.0.*", // v5.0.2
        "symfony/webpack-encore-bundle": "^1.4", // v1.7.2
        "symfony/yaml": "5.0.*", // v5.0.2
        "twig/cssinliner-extra": "^2.12", // v2.12.0
        "twig/extensions": "^1.5", // v1.5.4
        "twig/inky-extra": "^2.12" // v2.12.0
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.3.0
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/browser-kit": "5.0.*", // v5.0.2
        "symfony/debug-bundle": "5.0.*", // v5.0.2
        "symfony/maker-bundle": "^1.0", // v1.14.3
        "symfony/phpunit-bridge": "5.0.*", // v5.0.2
        "symfony/profiler-pack": "^1.0", // v1.0.4
        "symfony/var-dumper": "5.0.*" // v5.0.2