Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

The Twig Recipe

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.

Unless you're building a pure API - and we will talk about returning JSON later in this tutorial - you're going to need to write some HTML. And... putting text or HTML in a controller like this is... ugly.

No worries! Symfony has great integration with an incredible template library called Twig. There's just one problem: our Symfony app is so small that Twig isn't even installed yet! Ah, but that's not really a problem... thanks to the recipe system.

Installing Twig

Head back to https://flex.symfony.com and search for "template". There it is! Apparently Symfony's recommended "template" library is something called twig-pack. Let's install it!

composer require template

This installs a few packages... and yea! 2 recipes! Let's see what they did:

git status

Checking out the Recipe Changes

Whoa, awesome. Okay: we expected changes to composer.json, composer.lock and symfony.lock. Everything else was done by those recipes.

What are Bundles?

Let's look at bundles.php first:

git diff config/bundles.php

Interesting: it added two lines. Go open that: config/bundles.php.

... lines 1 - 2
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],

A "bundle" is a Symfony plugin. Pretty commonly, when you want to add a new feature to your app, you'll install a bundle. And when you install a bundle, you need to enable it in your application. A long time ago, doing this was manual. But thanks to Symfony Flex, whenever you install a Symfony bundle, it automatically updates this to enable it for you. So... now that we've talked about this file, you'll probably never need to think about it again.

The templates/ Directory and Config

The recipe also added a templates/ directory. So if you were wondering where your templates are supposed to live... the recipe kinda answered that question! It also added a base.html.twig layout file that we'll talk about soon.

<!DOCTYPE html>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}

So... apparently our templates are supposed to live in templates/. But why? I mean, is that path hardcoded deep in some core Twig file? Nope! It lives right in our code, thanks to a twig.yaml file that was created by the recipe. Let's check that out: config/packages/twig.yaml.

default_path: '%kernel.project_dir%/templates'

We're going to talk more about these YAML files in another tutorial. But without understanding a lot about this file, it... already makes sense! This default_path config points to the templates/ directory. Want your templates to live somewhere else? Just change this and... done! You're in control.

By the way, don't worry about this weird %kernel.project_dir% syntax. We'll learn about that later. But basically, it's a fancy way to point to the root of our project.

The recipe also created one other twig.yaml file which is less important: config/packages/test/twig.yaml. This makes a tiny change to Twig inside your automated tests. The details don't really matter. The point is: we installed Twig and its recipe handled everything else. We are 100% ready to use it in our app. Let's do that next.

Leave a comment!

Login or Register to join the conversation
Nahom B. Avatar
Nahom B. Avatar Nahom B. | posted 2 years ago

Hi guys there is best way to create controller with php bin/console make:controller and it ask you a name like PizzaController and it create a controller with a folder and file in template


Hey Nahom B.!

Yes, you're totally right! I love that command - we only don't show it here because I want people to get used to what steps are necessary for a route, controller and template. But in a real project, yea, use it!


Federico R. Avatar
Federico R. Avatar Federico R. | posted 3 years ago


There's a way you can make a start project with all the recipes you need? Or you have to call every project from zero?

Thanks in advance


Hey Federico R.

When you install a bundle Symfony Flex installs any recipes that it comes with. So, in a new project you'll have to install all the bundles that you will need. Installing recipes without its correspondent bundle makes no sense because you will be adding configuration files and structure that nothing in your application will use


Richard Avatar
Richard Avatar Richard | posted 3 years ago

Why is it that I can "composer require template" yet "composer recipes template" says no such recipe? That's very confusing since any install requires a recipe...


Hey Maxii123,

Good question! I don't know the exact reason why "composer recipes" command does not work with aliases fairly speaking. Feel free to ask this question on symfony/symfony repository. Probably it's just a lack of implementation for now. Or probably there're some other blocking reasons behind of this that I don't know.


Cat in space

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

This tutorial also works great for Symfony 6!

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": "^7.3.0 || ^8.0.0",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "easycorp/easy-log-handler": "^1.0.7", // v1.0.9
        "sensio/framework-extra-bundle": "^6.0", // v6.2.1
        "symfony/asset": "5.0.*", // v5.0.11
        "symfony/console": "5.0.*", // v5.0.11
        "symfony/debug-bundle": "5.0.*", // v5.0.11
        "symfony/dotenv": "5.0.*", // v5.0.11
        "symfony/flex": "^1.3.1", // v1.17.5
        "symfony/framework-bundle": "5.0.*", // v5.0.11
        "symfony/monolog-bundle": "^3.0", // v3.5.0
        "symfony/profiler-pack": "*", // v1.0.5
        "symfony/routing": "5.1.*", // v5.1.11
        "symfony/twig-pack": "^1.0", // v1.0.1
        "symfony/var-dumper": "5.0.*", // v5.0.11
        "symfony/webpack-encore-bundle": "^1.7", // v1.8.0
        "symfony/yaml": "5.0.*" // v5.0.11
    "require-dev": {
        "symfony/profiler-pack": "^1.0" // v1.0.5