Symfony: 10 – Twig templates

A template is simply a text file that can generate any text-based format (HTML, XML, CSV, LaTeX, etc.). Symfony packages powerful templating language called Twig. Twig comes with a long list of tags and filters that are available by default. Each Twig template is compiled down to a native PHP class that is rendered at runtime. The compiled classes are located in the app/cache/{environment}/twig directory.

When debug mode is enabled (common in the dev environment), a Twig template will be automatically recompiled when changes are made to it. When debug mode is disabled (common in the prod environment), however, you must clear the Twig cache directory so that the Twig templates will regenerate.

When generating HTML from a template, there is always a risk that a template variable may output unintended HTML or dangerous client-side code. If you’re using Twig, output escaping is on by default and you’re protected.

Twig defines three types of special syntax:

  • {{ … }} prints a variable or the result of an expression to the template
  • {% … %} controls the logic of the template; it is used to execute statements such as for-loops
  • {# … #} equivalent of the PHP /* comment */ syntax

Template Inheritance and Layouts

A child template can extend the base layout and override any of its blocks.

// app/Resources/views/base.html.twig
{% block body %}{% endblock %}
 
 
// The parent template is identified by a special string syntax (base.html.twig)
// This path is relative to the app/Resources/views directory of the project
// app/Resources/views/blog/index.html.twig
{% extends 'base.html.twig' %}
 
{% block body %}
    {% for entry in blog_entries %}

{{ entry.title }}

{{ entry.body }}

    {% endfor %}
{% endblock %}

If you need to get the content of a block from the parent template, you can use the {{ parent() }} function.

By default, templates can live in two different locations:

app/Resources/views/
The applications views directory can contain application-wide base templates (i.e. your application’s layouts and templates of the application bundle) as well as templates that override third party bundle templates.

path/to/bundle/Resources/views/
Each third party bundle houses its templates in its Resources/views/ directory. When you plan to share your bundle, you should put the templates in the bundle instead of the app/ directory.

Most of the templates you’ll use live in the app/Resources/views/ directory. To render/extend app/Resources/views/base.html.twig, you’ll use the base.html.twig path and to render/extend app/Resources/views/blog/index.html.twig, you’ll use the blog/index.html.twig path.

You can include an other template using the {{ include() }} function. Notice that the template name follows the same typical convention. The article_details.html.twig template uses an article variable, which we pass to it:

{# app/Resources/views/article/list.html.twig #}
{% extends 'layout.html.twig' %}
 
{% block body %}

Recent Articles

{% for article in articles %} {{ include(‘article/article_details.html.twig’, { ‘article’: article }) }} {% endfor %} {% endblock %}

Embedding Controllers

In some cases, you need to do more than include a simple template, like retrieving a list of the five articles. Whenever you find that you need a variable or a piece of information that you don’t have access to in a template, consider rendering a controller. Controllers are fast to execute. Like all controllers, they should ideally be skinny, meaning that as much code as possible lives in reusable services.

// src/AppBundle/Controller/ArticleController.php
public function recentArticlesAction($max = 3)
    {
        $articles = ...;
 
        return $this->render(
            'article/recent_list.html.twig',
            array('articles' => $articles)
        );
    }
 
// Refer to controller using the standard string syntax for controllers (i.e. bundle:controller:action)

Linking to Pages
Creating links to other pages in your application is one of the most common jobs for a template. Instead of hardcoding URLs in templates, use the path Twig function (or the router helper in PHP) to generate URLs based on the routing configuration. Later, if you want to modify the URL of a particular page, all you’ll need to do is change the routing configuration; the templates will automatically generate the new URL.

  <a href="{{ path('_welcome') }}">Home</a>
 
  <a href="{{ path('article_show', {'slug': article.slug}) }}">
        {{ article.title }}
  </a>
 
  // You can also generate an absolute URL by using the url Twig function
  <a href="{{ url('_welcome') }}">Home</a>

The {% extends %} tag tells the templating engine to first evaluate the base template. The child template is then rendered, at which point the body blocks of the parent are replaced by those from the child.

Linking to Assets

Templates also commonly refer to images, JavaScript, stylesheets and other assets. Symfony provides the asset Twig function:

<img src="{{ asset('images/logo.png') }}" alt="Symfony!" />
 
 
 
// Use of assets_version
<img src="{{ asset('images/logo.png', version='3.0') }}" alt="Symfony!" />
 
// Use of absolute URLs
<img src="{{ asset('images/logo.png', absolute=true) }}" alt="Symfony!" />

Additionally, if you use the asset function, Symfony can automatically append a query string to your asset, in order to guarantee that updated static assets won’t be cached when deployed. see the assets_version configuration option.

{# app/Resources/views/base.html.twig #}
        {# ... #}

        {% block stylesheets %}
 
        {% endblock %}
    {# ... #}

        {% block javascripts %}<script src="{{ asset('js/main.js') }}"></script>{% endblock %}

Suppose you have a contact page and you need to include a contact.css stylesheet just on that page. From inside that contact page’s template, do the following:

{# app/Resources/views/contact/contact.html.twig #}
{% extends 'base.html.twig' %}
 
{% block stylesheets %}
    {{ parent() }}
 
 
{% endblock %}

You can also include assets located in your bundles’ Resources/public folder. You will need to run the php app/console assets:install target [–symlink] command, which moves (or symlinks) files into the correct location (target is by default “web”).

During each request, Symfony will set a global template variable app in both Twig and PHP template engines by default. The app variable is a GlobalVariables instance which will give you access to some application specific variables automatically.

You can use the templating engine service to render a template in a controller:

return $this-&gt;render('article/index.html.twig');

You can check for syntax errors in Twig templates using the twig:lint console command:

# You can check by filename:
php app/console twig:lint app/Resources/views/article/recent_list.html.twig
 
# or by directory:
php app/console twig:lint app/Resources/views

Symfony Twig Extensions

By itself Twig already contains a lot of built-in functions. Symfony adds custom extensions on top of Twig to integrate some components into the Twig templates.


Leave a Reply