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!

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