Updating the TwigBundle Recipe

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.

Start your All-Access Pass
Buy just this tutorial for $10.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

The updated framework-bundle recipe gave us this new routing file: config/routes/dev/framework.yaml:

resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

Which loads a /_error/{statusCode} route where we can test what our production error pages look like.

This feature used to live in TwigBundle... which is why twig.yaml has basically the exact same import:

resource: '@TwigBundle/Resources/config/routing/errors.xml'
prefix: /_error

This is a minor problem. In your terminal, run:

php bin/console debug:router

and scroll up to the top. Yep! We have two routes for the exact same URL. The first one - which by chance is the one from FrameworkBundle - would win, but we still don't want the old one sitting there. Plus, it's deprecated and will disappear in Symfony 5.

We need to delete this twig.yaml file. But... we probably also need to update the TwigBundle recipe... which will probably delete it for us. Run:

composer recipes

Yep! The recipe for symfony/twig-bundle has an update.

Updating symfony/twig-bundle Recipe

Get some info about it:

composer recipes symfony/twig-bundle

Then copy the recipes:install command and run it:

composer recipes:install symfony/twig-bundle --force -v

Perfect! It looks like it modified three files. Let's start walking through them:

git add -p

The first change is inside the twig.yaml config file. If you ignore the stuff that it's removing - that's all our custom code - it looks like the updated recipe added a line: exception_controller: null.

Ok, so we definitely want to keep our custom changes... and we probably want to keep this new line... except that we don't really know why it was added.


Let's go do some digging! But this time, instead of checking the recipe commit history, let's try something different. Because this is a config change for TwigBundle, let's go see if they mention this in a CHANGELOG.

Google for "GitHub TwigBundle" to find its GitHub page. Scroll down and... yea! It has a CHANGELOG.md file.

Open it up and look at the 4.4.0 changes. Actually, this exception_controller change could even be from an earlier version - but we'll start here. And... yea, it does talk about it:

deprecated twig.exception_controller configuration option, set it to "null" and use framework.error_controller configuration instead.

The deprecated twig exception_controller Option

This is another feature that was deprecated inside TwigBundle and moved to FrameworkBundle. The exception, or "error", controller is the controller that's responsible for rendering an error page.

To disable - basically "stop using" the deprecated old code - we need to set exception_controller to null. That is why the recipe added this change. This is a good change. Of course, if your config file already has an exception_controller option... because you're using a custom exception controller, you'll need to move that value to framework.error_controller and do some reading to see if your controller code needs any other updates.

So we do want this change... but we can't accept this patch without killing our custom code. Copy the new config, hit "q" to quit this mode, and then... let's see - undo those changes by running:

git checkout config/packages/twig.yaml

Oh, and I guess I should spell "checkout" right.

Now, spin back over, open that file - config/packages/twig.yaml - and add exception_controller: null:

... lines 2 - 9
exception_controller: null

Nice! Let's... keep going: start the git add -p system again:

git add -p

This time we do want to accept the change to twig.yaml - "y" - and the next change is inside symfony.lock. Accept that too.

base.html.twig and the new test/twig.yaml

The last updated file is templates/base.html.twig and we definitely do not want to accept this change and kill our custom layout. Looking at the new code... I don't see anything super important that we might want to add. In fact, if you checked the recipe history, there haven't been any updates to this file in years. Hit "n" to ignore this.


git status

to see how things look. Oh! A new file: config/packages/test/twig.yaml - a config file that's only loaded in the test environment. Before we see what's inside it, let's revert the changes we don't want:

git checkout templates/base.html.twig

Go open the new file: config/packages/test/twig.yaml:

strict_variables: true

Ah, super minor: it sets strict_variables to true for our tests. This settings tells Twig to throw an exception if we try to use an undefined variable in a template. If we ever did that, we probably would want Twig to explode in our tests so we know about it. That's a good change. Add that file:

git add config/packages/test/twig.yaml

Manually Deleting config/routes/dev/twig.yaml

We're done! But... wait a second. We expected that the updated recipe would delete the extra config/routes/dev/twig.yaml file... but it didn't. Hmm... is it still in the recipe for some reason? Run:

composer recipes symfony/twig-bundle

Copy the URL to the recipe... and paste it in your browser. Huh. No - there is no config/routes directory at all in here. The file is gone! Why wasn't it deleted?

This is a shortcoming of the recipe update system: it's not smart enough. In a perfect world, it would realize that there used to be a config/routes/dev/twig.yaml file in the old version of the recipe... and since it is not there in the new version, it would delete it. But, that does not happen, at least not yet.

So, we need to delete it manually. This doesn't happen very often, but it is something you should be aware of.

Back at the terminal, run:

git status

one more time - things look good - and let's commit:

git commit -m "updating symfony/twig-bundle"

Nice! Now run:

composer recipes

We're getting close! Let's do any easy one next: let's upgrade symfony/mailer and symfony/sendgrid-mailer.

Leave a comment!

  • 2020-04-10 Vladimir Sadicov

    Ok, lets try another way, try to upgrade flex package with composer upgrade symfony/flex

  • 2020-04-10 hanene

    I use cmder terminal on wind 7

  • 2020-04-10 Vladimir Sadicov

    Hello hanene

    I think it might be related with your environment. Probably not all paths are registered in Windows environment. It's quite difficult to advice something. Which shell and Windows version do you use?

    BTW for best work behavior I would recommend to use WSL shell with Windows 10


  • 2020-04-09 hanene

    I run
    git init
    git satus
    modified: composer.json
    modified: composer.lock
    modified: config/bundles.php
    modified: symfony.lock

    git add .

    >composer recipes:install "symfony/twig-bundle" --force -v
    Could not open input file: D:\doc\test\quick_tour\composer.phar

  • 2020-04-08 Diego Aguiar

    Hey hanene

    I'm wondering it's telling you that git was not found. My first guess is that you haven't initialized git in your project. Let me know if that's not the case so we can figure this out


  • 2020-04-08 hanene

    Hello !! ..While trying to upgrade my project from symfony 4.2 to symfony 5 I couldn't update recipes for exple
    when I run composer recipes:install "symfony/twig-bundle" --force -v
    I got the error:
    Cannot run "sync-recipes --force": git not found.
    Exception trace:
    () at D:\doc\test\quick_tour\vendor\symfony\flex\src\Command\InstallRecipesCommand.php:54
    Symfony\Flex\Command\InstallRecipesCommand->execute() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Command/Command.php:245
    Symfony\Component\Console\Command\Command->run() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Application.php:835
    Symfony\Component\Console\Application->doRunCommand() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Application.php:185
    Symfony\Component\Console\Application->doRun() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Console/Application.php:258
    Composer\Console\Application->doRun() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Application.php:117
    Symfony\Component\Console\Application->run() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Console/Application.php:104
    Composer\Console\Application->run() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/bin/composer:61
    require() at C:\ProgramData\ComposerSetup\bin\composer.phar:24

    I googled a little and tried execute this command composer sync-recipes --force
    but still getting the same error [Symfony\Component\Console\Exception\RuntimeException]
    Cannot run "sync-recipes --force": git not found.

  • 2020-03-30 Victor Bocharsky

    Hey AymDev,

    Hm, probably there's a reason that it works slightly different with --no-interaction option. But as I understand, you can kind of "jump" into container and execute that some command but without --no-interaction option now. Probably it would help.

    Anyway, glad you found a workaround!


  • 2020-03-27 AymDev

    Hi Victor,

    I re-updated the recipe in Git detached HEAD state by executing the command locally and you were right, it works nice :-)
    The issue must come from the container, sad I can't use the --no-interaction option but hopefully that's not for an everyday command !

    Sorry for your time and thanks again for your answers !

  • 2020-03-27 Victor Bocharsky

    Hey AymDev,

    Hm, difficult to day more about it. You could try to do the same but locally (not in your Docker container). It should behave the same. I don't think it should be any different behavior in for interactive and non-interactive mode, but I'm not 100% sure.

    The only possible reason I see is that your project just does not have any changes in those existent files.


  • 2020-03-26 AymDev

    Hi Victor,

    I updated the Twig recipe, and saw that id did not modify ./templates/base.html.twig or ./config/packages/twig.yaml as shown on this video at 1:25, it only created the ./config/packages/test/twig.yaml.
    I understood by following this tutorial (for the 2nd time, by the way) that it modifies file even if it says "Created", but my base template was not modified, and my twig.yaml neither, that's why I think it is working incorrectly.

    Maybe it is normal to not overwrite existing files in non-interactive mode when no git repository has been found but I found it counter-intuitive. Maybe I should dig more in the source code, haha !

  • 2020-03-26 Victor Bocharsky

    Hey AymDev,

    Well, it depends on changes :) Why do you think the command works incorrectly? From the output, I see it does work properly, its output is totally valid. Well, IIRC it always says "Created ..." but technically it may create a new file or *modify* existent :)


  • 2020-03-25 AymDev

    Hi, SymfonyCasts team !

    I dockerized my own app which works great, but the Symfony code lies in the /app/ directory of my Git project. I think that's why I got the annoying confirmation messages according to this source code.

    But using the wonderful process of git add -p and git checkout I surely wanted to overwrite and then check which changes to commit. I used the --no-interaction option but it did not modify the files as I expected, only created new ones. Is this normal ? I don't know if it worths opening an issue on GitHub.
    Here is the complete command I executed (docker exec -it app tells docker to execute a command in the container) and its output:

    $> docker exec -it app composer recipes:install --no-interaction symfony/twig-bundle --force -v

    Symfony operations: 1 recipe (a163a92832df72d8c7b4f86bf8da9837)
    - Configuring symfony/twig-bundle (>=4.4): From github.com/symfony/recipes:master
    Enabling the package as a Symfony bundle
    Copying files from recipe
    Created "./config/packages/test/twig.yaml"

    EDIT: I don't think that's a file permission issue as it correctly modifies file when I answer the interactive overwrite questions using the same command without the --no-interaction option.

    Cheers !

  • 2020-02-20 Vasiljev.Alexey

    weaverryan No problem, love your tuts. Save me tons of time in real projects. Thank you and your team for your work! :)
    And one more thing about git commits. Standartisation for...
    * Capitalized
    * In imperative present tense
    Naming convention git commit messages
    It should be read like "If applied it will"... 'Update symfony/twig-bundle'

  • 2020-02-20 weaverryan

    Hey Vasiljev.Alexey!

    You're right! I've never really "gotten into" some of the other options inside "git patch" :). I do use the split "s" when possible - but not edit. I'll have to try that!

    Thanks for the tip - and cheers :)

  • 2020-02-20 Vasiljev.Alexey

    You should've tried 'e' (edit) option in [y,n,q,a,d,s,e,?] set when accepting git patch. You can selectively accept changes.
    And another handy thing for new git files. You can just add file to git stage but not its contents with git add -N /path/to/file. And after that you can add its contents via git add -p /path/to/file.