blob: 7f1c1e8c1b8dd45825fb8edbcb6234640c9e329e [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001``extends``
2===========
3
4The ``extends`` tag can be used to extend a template from another one.
5
6.. note::
7
8 Like PHP, Twig does not support multiple inheritance. So you can only have
9 one extends tag called per rendering. However, Twig supports horizontal
10 :doc:`reuse<use>`.
11
12Let's define a base template, ``base.html``, which defines a simple HTML
13skeleton document:
14
15.. code-block:: html+twig
16
17 <!DOCTYPE html>
18 <html>
19 <head>
20 {% block head %}
21 <link rel="stylesheet" href="style.css"/>
22 <title>{% block title %}{% endblock %} - My Webpage</title>
23 {% endblock %}
24 </head>
25 <body>
26 <div id="content">{% block content %}{% endblock %}</div>
27 <div id="footer">
28 {% block footer %}
29 &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
30 {% endblock %}
31 </div>
32 </body>
33 </html>
34
35In this example, the :doc:`block<block>` tags define four blocks that child
36templates can fill in.
37
38All the ``block`` tag does is to tell the template engine that a child
39template may override those portions of the template.
40
41Child Template
42--------------
43
44A child template might look like this:
45
46.. code-block:: html+twig
47
48 {% extends "base.html" %}
49
50 {% block title %}Index{% endblock %}
51 {% block head %}
52 {{ parent() }}
53 <style type="text/css">
54 .important { color: #336699; }
55 </style>
56 {% endblock %}
57 {% block content %}
58 <h1>Index</h1>
59 <p class="important">
60 Welcome on my awesome homepage.
61 </p>
62 {% endblock %}
63
64The ``extends`` tag is the key here. It tells the template engine that this
65template "extends" another template. When the template system evaluates this
66template, first it locates the parent. The extends tag should be the first tag
67in the template.
68
69Note that since the child template doesn't define the ``footer`` block, the
70value from the parent template is used instead.
71
72You can't define multiple ``block`` tags with the same name in the same
73template. This limitation exists because a block tag works in "both"
74directions. That is, a block tag doesn't just provide a hole to fill - it also
75defines the content that fills the hole in the *parent*. If there were two
76similarly-named ``block`` tags in a template, that template's parent wouldn't
77know which one of the blocks' content to use.
78
79If you want to print a block multiple times you can however use the
80``block`` function:
81
82.. code-block:: html+twig
83
84 <title>{% block title %}{% endblock %}</title>
85 <h1>{{ block('title') }}</h1>
86 {% block body %}{% endblock %}
87
88Parent Blocks
89-------------
90
91It's possible to render the contents of the parent block by using the
92:doc:`parent<../functions/parent>` function. This gives back the results of
93the parent block:
94
95.. code-block:: html+twig
96
97 {% block sidebar %}
98 <h3>Table Of Contents</h3>
99 ...
100 {{ parent() }}
101 {% endblock %}
102
103Named Block End-Tags
104--------------------
105
106Twig allows you to put the name of the block after the end tag for better
107readability (the name after the ``endblock`` word must match the block name):
108
109.. code-block:: twig
110
111 {% block sidebar %}
112 {% block inner_sidebar %}
113 ...
114 {% endblock inner_sidebar %}
115 {% endblock sidebar %}
116
117Block Nesting and Scope
118-----------------------
119
120Blocks can be nested for more complex layouts. Per default, blocks have access
121to variables from outer scopes:
122
123.. code-block:: html+twig
124
125 {% for item in seq %}
126 <li>{% block loop_item %}{{ item }}{% endblock %}</li>
127 {% endfor %}
128
129Block Shortcuts
130---------------
131
132For blocks with little content, it's possible to use a shortcut syntax. The
133following constructs do the same thing:
134
135.. code-block:: twig
136
137 {% block title %}
138 {{ page_title|title }}
139 {% endblock %}
140
141.. code-block:: twig
142
143 {% block title page_title|title %}
144
145Dynamic Inheritance
146-------------------
147
148Twig supports dynamic inheritance by using a variable as the base template:
149
150.. code-block:: twig
151
152 {% extends some_var %}
153
154If the variable evaluates to a ``\Twig\Template`` or a ``\Twig\TemplateWrapper``
155instance, Twig will use it as the parent template::
156
157 // {% extends layout %}
158
159 $layout = $twig->load('some_layout_template.twig');
160
161 $twig->display('template.twig', ['layout' => $layout]);
162
163You can also provide a list of templates that are checked for existence. The
164first template that exists will be used as a parent:
165
166.. code-block:: twig
167
168 {% extends ['layout.html', 'base_layout.html'] %}
169
170Conditional Inheritance
171-----------------------
172
173As the template name for the parent can be any valid Twig expression, it's
174possible to make the inheritance mechanism conditional:
175
176.. code-block:: twig
177
178 {% extends standalone ? "minimum.html" : "base.html" %}
179
180In this example, the template will extend the "minimum.html" layout template
181if the ``standalone`` variable evaluates to ``true``, and "base.html"
182otherwise.
183
184How do blocks work?
185-------------------
186
187A block provides a way to change how a certain part of a template is rendered
188but it does not interfere in any way with the logic around it.
189
190Let's take the following example to illustrate how a block works and more
191importantly, how it does not work:
192
193.. code-block:: html+twig
194
195 {# base.twig #}
196 {% for post in posts %}
197 {% block post %}
198 <h1>{{ post.title }}</h1>
199 <p>{{ post.body }}</p>
200 {% endblock %}
201 {% endfor %}
202
203If you render this template, the result would be exactly the same with or
204without the ``block`` tag. The ``block`` inside the ``for`` loop is just a way
205to make it overridable by a child template:
206
207.. code-block:: html+twig
208
209 {# child.twig #}
210 {% extends "base.twig" %}
211
212 {% block post %}
213 <article>
214 <header>{{ post.title }}</header>
215 <section>{{ post.text }}</section>
216 </article>
217 {% endblock %}
218
219Now, when rendering the child template, the loop is going to use the block
220defined in the child template instead of the one defined in the base one; the
221executed template is then equivalent to the following one:
222
223.. code-block:: html+twig
224
225 {% for post in posts %}
226 <article>
227 <header>{{ post.title }}</header>
228 <section>{{ post.text }}</section>
229 </article>
230 {% endfor %}
231
232Let's take another example: a block included within an ``if`` statement:
233
234.. code-block:: html+twig
235
236 {% if posts is empty %}
237 {% block head %}
238 {{ parent() }}
239
240 <meta name="robots" content="noindex, follow">
241 {% endblock head %}
242 {% endif %}
243
244Contrary to what you might think, this template does not define a block
245conditionally; it just makes overridable by a child template the output of
246what will be rendered when the condition is ``true``.
247
248If you want the output to be displayed conditionally, use the following
249instead:
250
251.. code-block:: html+twig
252
253 {% block head %}
254 {{ parent() }}
255
256 {% if posts is empty %}
257 <meta name="robots" content="noindex, follow">
258 {% endif %}
259 {% endblock head %}
260
261.. seealso::
262
263 :doc:`block<../functions/block>`, :doc:`block<../tags/block>`, :doc:`parent<../functions/parent>`, :doc:`use<../tags/use>`