Twig Templates

Twig is the default templating engine for Symfony views. Rather than mixing raw PHP into your HTML, Twig gives you a clean, compact syntax purpose-built for templates. The single biggest reason to prefer it over plain PHP for views is safety: Twig auto-escapes every variable it prints by default, so output is HTML-escaped automatically and cross-site scripting (XSS) is prevented out of the box. You have to explicitly opt out with the |raw filter if you really want unescaped output — the safe behavior is the default, not something you have to remember to add.

Basic Twig Syntax

Twig has three kinds of delimiters, each with a distinct job:

SyntaxPurpose
{{ variable }}Prints a variable's value — output is auto-escaped
{% if %} ... {% endif %}Control structures such as conditionals
{% for item in items %} ... {% endfor %}Loops over an array or collection
{% extends 'base.html.twig' %}Template inheritance — reuse a parent layout
{% block content %} ... {% endblock %}Defines a named block a child template can override
Note: Twig files are not PHP, so the examples below are shown without PHP syntax highlighting — the {{ }} and {% %} delimiters are Twig's own syntax, unrelated to PHP tags.

A Worked Example: show.html.twig

Recall the minimal controller from the Controllers page — it called $this->render('article/show.html.twig', ['id' => $id]). That second argument is an array of variables handed to the template. Here's a template that could receive data like that (imagine the controller also passing an article object and a list of tags):

{% extends 'base.html.twig' %}

{% block content %}
    <h1>{{ article.title }}</h1>

    <p>{{ article.content }}</p>

    {% if tags is not empty %}
        <ul>
        {% for tag in tags %}
            <li>{{ tag }}</li>
        {% endfor %}
        </ul>
    {% else %}
        <p>No tags for this article.</p>
    {% endif %}
{% endblock %}

This template extends a shared base.html.twig layout and only fills in the content block — the surrounding HTML (head, navigation, footer) lives once in the parent template instead of being repeated on every page.

Twig Filters

Filters transform a value before it's printed, using the pipe (|) syntax. They're handy for formatting data without writing PHP logic inside the template.

{{ name|upper }}

{{ price|number_format(2) }}

name|upper prints the name variable converted to uppercase. price|number_format(2) formats a numeric price value to two decimal places, exactly like PHP's number_format() function — Twig ships with a large library of built-in filters for strings, numbers, arrays, and dates.

Next steps: Templates render data, but that data usually comes from a database. Head to Doctrine ORM to see how Symfony maps PHP objects to database tables.