As you know, the controller is responsible for
handling each request that comes into a Symfony application. In reality,
the controller delegates most of the heavy work to other places so that
code can be tested and reused. When a controller needs to generate HTML,
CSS or any other content, it hands the work off to the templating engine.
In this chapter, you'll learn how to write powerful templates that can be
used to return content to the user, populate email bodies, and more. You'll
learn shortcuts, clever ways to extend templates and how to reuse template
code.

Note

How to render templates is covered in the controller
page of the book.

A template is simply a text file that can generate any text-based format
(HTML, XML, CSV, LaTeX ...). The most familiar type of template is a PHP
template - a text file parsed by PHP that contains a mix of text and PHP code:

But Symfony packages an even more powerful templating language called Twig.
Twig allows you to write concise, readable templates that are more friendly
to web designers and, in several ways, more powerful than PHP templates:

Registering a Twig extension is as easy as creating a new service and tagging
it with twig.extensiontag.

As you'll see throughout the documentation, Twig also supports functions
and new functions can be easily added. For example, the following uses a
standard for tag and the cycle function to print ten div tags, with
alternating odd, even classes:

Throughout this chapter, template examples will be shown in both Twig and PHP.

Tip

If you do choose to not use Twig and you disable it, you'll need to implement
your own exception handler via the kernel.exception event.

Why Twig?

Twig templates are meant to be simple and won't process PHP tags. This
is by design: the Twig template system is meant to express presentation,
not program logic. The more you use Twig, the more you'll appreciate
and benefit from this distinction. And of course, you'll be loved by
web designers everywhere.

Twig can also do things that PHP can't, such as whitespace control,
sandboxing, automatic and contextual output escaping, and the inclusion of
custom functions and filters that only affect templates. Twig contains
little features that make writing templates easier and more concise. Take
the following example, which combines a loop with a logical if
statement:

Twig is fast. 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 (where {environment} is the
environment, such as dev or prod) and in some cases can be useful
while debugging. See Environments for more information on
environments.

When debug mode is enabled (common in the dev environment), a Twig
template will be automatically recompiled when changes are made to it. This
means that during development you can happily make changes to a Twig template
and instantly see the changes without needing to worry about clearing any
cache.

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. Remember to do this when deploying your application.

More often than not, templates in a project share common elements, like the
header, footer, sidebar or more. In Symfony, this problem is thought about
differently: a template can be decorated by another one. This works
exactly the same as PHP classes: template inheritance allows you to build
a base "layout" template that contains all the common elements of your site
defined as blocks (think "PHP class with base methods"). A child template
can extend the base layout and override any of its blocks (think "PHP subclass
that overrides certain methods of its parent class").

Though the discussion about template inheritance will be in terms of Twig,
the philosophy is the same between Twig and PHP templates.

This template defines the base HTML skeleton document of a simple two-column
page. In this example, three {% block %} areas are defined (title,
sidebar and body). Each block may be overridden by a child template
or left with its default implementation. This template could also be rendered
directly. In that case the title, sidebar and body blocks would
simply retain the default values used in this template.

The parent template is identified by a special string syntax
(::base.html.twig) that indicates that the template lives in the
app/Resources/views directory of the project. This naming convention is
explained fully in Template Naming and Locations.

The key to template inheritance is the {% extends %} tag. This tells
the templating engine to first evaluate the base template, which sets up
the layout and defines several blocks. The child template is then rendered,
at which point the title and body blocks of the parent are replaced
by those from the child. Depending on the value of blog_entries, the
output might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<!DOCTYPE html><html><head><metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/><title>My cool blog posts</title></head><body><divid="sidebar"><ul><li><ahref="/">Home</a></li><li><ahref="/blog">Blog</a></li></ul></div><divid="content"><h2>My first post</h2><p>The body of the first post.</p><h2>Another post</h2><p>The body of the second post.</p></div></body></html>

Notice that since the child template didn't define a sidebar block, the
value from the parent template is used instead. Content within a {% block %}
tag in a parent template is always used by default.

You can use as many levels of inheritance as you want. In the next section,
a common three-level inheritance model will be explained along with how templates
are organized inside a Symfony project.

When working with template inheritance, here are some tips to keep in mind:

If you use {% extends %} in a template, it must be the first tag in
that template;

The more {% block %} tags you have in your base templates, the better.
Remember, child templates don't have to define all parent blocks, so create
as many blocks in your base templates as you want and give each a sensible
default. The more blocks your base templates have, the more flexible your
layout will be;

If you find yourself duplicating content in a number of templates, it probably
means you should move that content to a {% block %} in a parent template.
In some cases, a better solution may be to move the content to a new template
and include it (see Including other Templates);

If you need to get the content of a block from the parent template, you
can use the {{ parent() }} function. This is useful if you want to add
to the contents of a parent block instead of completely overriding it:

Blog: (controller) indicates that the template lives inside the
Blog subdirectory of Resources/views;

index.html.twig: (template) the actual name of the file is
index.html.twig.

Assuming that the AcmeBlogBundle lives at src/Acme/BlogBundle, the
final path to the layout would be src/Acme/BlogBundle/Resources/views/Blog/index.html.twig.

AcmeBlogBundle::layout.html.twig: This syntax refers to a base template
that's specific to the AcmeBlogBundle. Since the middle, "controller",
portion is missing (e.g. Blog), the template lives at
Resources/views/layout.html.twig inside AcmeBlogBundle.

::base.html.twig: This syntax refers to an application-wide base template
or layout. Notice that the string begins with two colons (::), meaning
that both the bundle and controller portions are missing. This means
that the template is not located in any bundle, but instead in the root
app/Resources/views/ directory.

In the Overriding Bundle Templates section, you'll find out how each
template living inside the AcmeBlogBundle, for example, can be overridden
by placing a template of the same name in the app/Resources/AcmeBlogBundle/views/
directory. This gives the power to override templates from any vendor bundle.

Tip

Hopefully the template naming syntax looks familiar - it's the same naming
convention used to refer to Controller Naming Pattern.

The bundle:controller:template format of each template specifies
where the template file is located. Every template name also has two extensions
that specify the format and engine for that template.

AcmeBlogBundle:Blog:index.html.twig - HTML format, Twig engine

AcmeBlogBundle:Blog:index.html.php - HTML format, PHP engine

AcmeBlogBundle:Blog:index.css.twig - CSS format, Twig engine

By default, any Symfony template can be written in either Twig or PHP, and
the last part of the extension (e.g. .twig or .php) specifies which
of these two engines should be used. The first part of the extension,
(e.g. .html, .css, etc) is the final format that the template will
generate. Unlike the engine, which determines how Symfony parses the template,
this is simply an organizational tactic used in case the same resource needs
to be rendered as HTML (index.html.twig), XML (index.xml.twig),
or any other format. For more information, read the Template Formats
section.

You already understand the basics of templates, how they're named and how
to use template inheritance. The hardest parts are already behind you. In
this section, you'll learn about a large group of tools available to help
perform the most common template tasks such as including other templates,
linking to pages and including images.

Symfony comes bundled with several specialized Twig tags and functions that
ease the work of the template designer. In PHP, the templating system provides
an extensible helper system that provides useful features in a template
context.

You've already seen a few built-in Twig tags ({% block %} & {% extends %})
as well as an example of a PHP helper ($view['slots']). Here you will learn a
few more.

You'll often want to include the same template or code fragment on several
different pages. For example, in an application with "news articles", the
template code displaying an article might be used on the article detail page,
on a page displaying the most popular articles, or in a list of the latest
articles.

When you need to reuse a chunk of PHP code, you typically move the code to
a new PHP class or function. The same is true for templates. By moving the
reused template code into its own template, it can be included from any other
template. First, create the template that you'll need to reuse.

The template is included using the {{ include() }} function. Notice that the
template name follows the same typical convention. The articleDetails.html.twig
template uses an article variable, which we pass to it. In this case,
you could avoid doing this entirely, as all of the variables available in
list.html.twig are also available in articleDetails.html.twig (unless
you set with_context to false).

Tip

The {'article': article} syntax is the standard Twig syntax for hash
maps (i.e. an array with named keys). If you needed to pass in multiple
elements, it would look like this: {'foo': foo, 'bar': bar}.

In some cases, you need to do more than include a simple template. Suppose
you have a sidebar in your layout that contains the three most recent articles.
Retrieving the three articles may include querying the database or performing
other heavy logic that can't be done from within a template.

The solution is to simply embed the result of an entire controller from your
template. First, create a controller that renders a certain number of recent
articles:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// src/Acme/ArticleBundle/Controller/ArticleController.phpclassArticleControllerextendsController{publicfunctionrecentArticlesAction($max=3){// make a database call or other logic// to get the "$max" most recent articles$articles=...;return$this->render('AcmeArticleBundle:Article:recentList.html.twig',array('articles'=>$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 and promote good code organization and reuse.
Of course, like all controllers, they should ideally be "skinny", meaning
that as much code as possible lives in reusable services.

Controllers can be embedded asynchronously using the hinclude.js JavaScript library.
As the embedded content comes from another page (or controller for that matter),
Symfony uses a version of the standard render function to configure hinclude
tags:

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.

First, link to the "_welcome" page, which is accessible via the following routing
configuration:

In this case, you need to specify both the route name (article_show) and
a value for the {slug} parameter. Using this route, revisit the
recentList template from the previous section and link to the articles
correctly:

Templates also commonly refer to images, JavaScript, stylesheets and other
assets. Of course you could hard-code the path to these assets (e.g. /images/logo.png),
but Symfony provides a more dynamic option via the asset Twig function:

The asset function's main purpose is to make your application more portable.
If your application lives at the root of your host (e.g. http://example.com),
then the rendered paths should be /images/logo.png. But if your application
lives in a subdirectory (e.g. http://example.com/my_app), each asset path
should render with the subdirectory (e.g. /my_app/images/logo.png). The
asset function takes care of this by determining how your application is
being used and generating the correct paths accordingly.

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. For example, /images/logo.png might
look like /images/logo.png?v2. For more information, see the assets_version
configuration option.

No site would be complete without including JavaScript files and stylesheets.
In Symfony, the inclusion of these assets is handled elegantly by taking
advantage of Symfony's template inheritance.

Tip

This section will teach you the philosophy behind including stylesheet
and JavaScript assets in Symfony. Symfony also packages another library,
called Assetic, which follows this philosophy but allows you to do much
more interesting things with those assets. For more information on
using Assetic see How to Use Assetic for Asset Management.

Start by adding two blocks to your base template that will hold your assets:
one called stylesheets inside the head tag and another called javascripts
just above the closing body tag. These blocks will contain all of the
stylesheets and JavaScripts that you'll need throughout your site:

That's easy enough! But what if you need to include an extra stylesheet or
JavaScript from a child template? For example, 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:

In the child template, you simply override the stylesheets block and
put your new stylesheet tag inside of that block. Of course, since you want
to add to the parent block's content (and not actually replace it), you
should use the parent() Twig function to include everything from the stylesheets
block of the base template.

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:

The heart of the template system in Symfony is the templating Engine.
This special object is responsible for rendering templates and returning
their content. When you render a template in a controller, for example,
you're actually using the templating engine service. For example:

The Symfony community prides itself on creating and maintaining high quality
bundles (see KnpBundles.com) for a large number of different features.
Once you use a third-party bundle, you'll likely need to override and customize
one or more of its templates.

Suppose you've included the imaginary open-source AcmeBlogBundle in your
project (e.g. in the src/Acme/BlogBundle directory). And while you're
really happy with everything, you want to override the blog "list" page to
customize the markup specifically for your application. By digging into the
Blog controller of the AcmeBlogBundle, you find the following:

1
2
3
4
5
6
7
8
9
10

publicfunctionindexAction(){// some logic to retrieve the blogs$blogs=...;$this->render('AcmeBlogBundle:Blog:index.html.twig',array('blogs'=>$blogs));}

When the AcmeBlogBundle:Blog:index.html.twig is rendered, Symfony actually
looks in two different locations for the template:

app/Resources/AcmeBlogBundle/views/Blog/index.html.twig

src/Acme/BlogBundle/Resources/views/Blog/index.html.twig

To override the bundle template, just copy the index.html.twig template
from the bundle to app/Resources/AcmeBlogBundle/views/Blog/index.html.twig
(the app/Resources/AcmeBlogBundle directory won't exist, so you'll need
to create it). You're now free to customize the template.

Caution

If you add a template in a new location, you may need to clear your
cache (php app/console cache:clear), even if you are in debug mode.

This logic also applies to base bundle templates. Suppose also that each
template in AcmeBlogBundle inherits from a base template called
AcmeBlogBundle::layout.html.twig. Just as before, Symfony will look in
the following two places for the template:

app/Resources/AcmeBlogBundle/views/layout.html.twig

src/Acme/BlogBundle/Resources/views/layout.html.twig

Once again, to override the template, just copy it from the bundle to
app/Resources/AcmeBlogBundle/views/layout.html.twig. You're now free to
customize this copy as you see fit.

If you take a step back, you'll see that Symfony always starts by looking in
the app/Resources/{BUNDLE_NAME}/views/ directory for a template. If the
template doesn't exist there, it continues by checking inside the
Resources/views directory of the bundle itself. This means that all bundle
templates can be overridden by placing them in the correct app/Resources
subdirectory.

Since the Symfony framework itself is just a bundle, core templates can be
overridden in the same way. For example, the core TwigBundle contains
a number of different "exception" and "error" templates that can be overridden
by copying each from the Resources/views/Exception directory of the
TwigBundle to, you guessed it, the
app/Resources/TwigBundle/views/Exception directory.

Create individual templates for each page and make each extend the appropriate
section template. For example, the "index" page would be called something
close to AcmeBlogBundle:Blog:index.html.twig and list the actual blog posts.

Notice that this template extends the section template (AcmeBlogBundle::layout.html.twig)
which in-turn extends the base application layout (::base.html.twig).
This is the common three-level inheritance model.

When building your application, you may choose to follow this method or simply
make each page template extend the base application template directly
(e.g. {% extends '::base.html.twig' %}). The three-template model is
a best-practice method used by vendor bundles so that the base template for
a bundle can be easily overridden to properly extend your application's base
layout.

When generating HTML from a template, there is always a risk that a template
variable may output unintended HTML or dangerous client-side code. The result
is that dynamic content could break the HTML of the resulting page or allow
a malicious user to perform a Cross Site Scripting (XSS) attack. Consider
this classic example:

Twig

1

Hello {{name}}

PHP

1

Hello <?phpecho$name?>

Imagine the user enters the following code for their name:

1

<script>alert('hello!')</script>

Without any output escaping, the resulting template will cause a JavaScript
alert box to pop up:

1

Hello <script>alert('hello!')</script>

And while this seems harmless, if a user can get this far, that same user
should also be able to write JavaScript that performs malicious actions
inside the secure area of an unknowing, legitimate user.

The answer to the problem is output escaping. With output escaping on, the
same template will render harmlessly, and literally print the script
tag to the screen:

1

Hello &lt;script&gt;alert(&#39;helloe&#39;)&lt;/script&gt;

The Twig and PHP templating systems approach the problem in different ways.
If you're using Twig, output escaping is on by default and you're protected.
In PHP, output escaping is not automatic, meaning you'll need to manually
escape where necessary.

If you're using Twig templates, then output escaping is on by default. This
means that you're protected out-of-the-box from the unintentional consequences
of user-submitted code. By default, the output escaping assumes that content
is being escaped for HTML output.

In some cases, you'll need to disable output escaping when you're rendering
a variable that is trusted and contains markup that should not be escaped.
Suppose that administrative users are able to write articles that contain
HTML code. By default, Twig will escape the article body.

To render it normally, add the raw filter:

1

{{article.body|raw}}

You can also disable output escaping inside a {% block %} area or
for an entire template. For more information, see Output Escaping in
the Twig documentation.

Output escaping is not automatic when using PHP templates. This means that
unless you explicitly choose to escape a variable, you're not protected. To
use output escaping, use the special escape() view method:

1

Hello <?phpecho$view->escape($name)?>

By default, the escape() method assumes that the variable is being rendered
within an HTML context (and thus the variable is escaped to be safe for HTML).
The second argument lets you change the context. For example, to output something
in a JavaScript string, use the js context:

When using PHP, you can use var_dump() if you need to quickly find the
value of a variable passed. This is useful, for example, inside your controller.
The same can be achieved when using Twig thanks to the debug extension.

Templates are a generic way to render content in any format. And while in
most cases you'll use templates to render HTML content, a template can just
as easily generate JavaScript, CSS, XML or any other format you can dream of.

For example, the same "resource" is often rendered in several different formats.
To render an article index page in XML, simply include the format in the
template name:

XML template name: AcmeArticleBundle:Article:index.xml.twig

XML template filename: index.xml.twig

In reality, this is nothing more than a naming convention and the template
isn't actually rendered differently based on its format.

In many cases, you may want to allow a single controller to render multiple
different formats based on the "request format". For that reason, a common
pattern is to do the following:

The getRequestFormat on the Request object defaults to html,
but can return any other format based on the format requested by the user.
The request format is most often managed by the routing, where a route can
be configured so that /contact sets the request format to html while
/contact.xml sets the format to xml. For more information, see the
Advanced Example in the Routing chapter.

To create links that include the format parameter, include a _format
key in the parameter hash:

The templating engine in Symfony is a powerful tool that can be used each time
you need to generate presentational content in HTML, XML or any other format.
And though templates are a common way to generate content in a controller,
their use is not mandatory. The Response object returned by a controller
can be created with or without the use of a template:

Symfony's templating engine is very flexible and two different template
renderers are available by default: the traditional PHP templates and the
sleek and powerful Twig templates. Both support a template hierarchy and
come packaged with a rich set of helper functions capable of performing
the most common tasks.

Overall, the topic of templating should be thought of as a powerful tool
that's at your disposal. In some cases, you may not need to render a template,
and in Symfony, that's absolutely fine.