Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame^] | 1 | Twig for Template Designers |
| 2 | =========================== |
| 3 | |
| 4 | This document describes the syntax and semantics of the template engine and |
| 5 | will be most useful as reference to those creating Twig templates. |
| 6 | |
| 7 | Synopsis |
| 8 | -------- |
| 9 | |
| 10 | A template is a regular text file. It can generate any text-based format (HTML, |
| 11 | XML, CSV, LaTeX, etc.). It doesn't have a specific extension, ``.html`` or |
| 12 | ``.xml`` are just fine. |
| 13 | |
| 14 | A template contains **variables** or **expressions**, which get replaced with |
| 15 | values when the template is evaluated, and **tags**, which control the |
| 16 | template's logic. |
| 17 | |
| 18 | Below is a minimal template that illustrates a few basics. We will cover further |
| 19 | details later on: |
| 20 | |
| 21 | .. code-block:: html+twig |
| 22 | |
| 23 | <!DOCTYPE html> |
| 24 | <html> |
| 25 | <head> |
| 26 | <title>My Webpage</title> |
| 27 | </head> |
| 28 | <body> |
| 29 | <ul id="navigation"> |
| 30 | {% for item in navigation %} |
| 31 | <li><a href="{{ item.href }}">{{ item.caption }}</a></li> |
| 32 | {% endfor %} |
| 33 | </ul> |
| 34 | |
| 35 | <h1>My Webpage</h1> |
| 36 | {{ a_variable }} |
| 37 | </body> |
| 38 | </html> |
| 39 | |
| 40 | There are two kinds of delimiters: ``{% ... %}`` and ``{{ ... }}``. The first |
| 41 | one is used to execute statements such as for-loops, the latter outputs the |
| 42 | result of an expression. |
| 43 | |
| 44 | IDEs Integration |
| 45 | ---------------- |
| 46 | |
| 47 | Many IDEs support syntax highlighting and auto-completion for Twig: |
| 48 | |
| 49 | * *Textmate* via the `Twig bundle`_ |
| 50 | * *Vim* via the `Jinja syntax plugin`_ or the `vim-twig plugin`_ |
| 51 | * *Netbeans* via the `Twig syntax plugin`_ (until 7.1, native as of 7.2) |
| 52 | * *PhpStorm* (native as of 2.1) |
| 53 | * *Eclipse* via the `Twig plugin`_ |
| 54 | * *Sublime Text* via the `Twig bundle`_ |
| 55 | * *GtkSourceView* via the `Twig language definition`_ (used by gedit and other projects) |
| 56 | * *Coda* and *SubEthaEdit* via the `Twig syntax mode`_ |
| 57 | * *Coda 2* via the `other Twig syntax mode`_ |
| 58 | * *Komodo* and *Komodo Edit* via the Twig highlight/syntax check mode |
| 59 | * *Notepad++* via the `Notepad++ Twig Highlighter`_ |
| 60 | * *Emacs* via `web-mode.el`_ |
| 61 | * *Atom* via the `PHP-twig for atom`_ |
| 62 | * *Visual Studio Code* via the `Twig pack`_ |
| 63 | |
| 64 | Also, `TwigFiddle`_ is an online service that allows you to execute Twig templates |
| 65 | from a browser; it supports all versions of Twig. |
| 66 | |
| 67 | Variables |
| 68 | --------- |
| 69 | |
| 70 | The application passes variables to the templates for manipulation in the |
| 71 | template. Variables may have attributes or elements you can access, too. The |
| 72 | visual representation of a variable depends heavily on the application providing |
| 73 | it. |
| 74 | |
| 75 | Use a dot (``.``) to access attributes of a variable (methods or properties of a |
| 76 | PHP object, or items of a PHP array): |
| 77 | |
| 78 | .. code-block:: twig |
| 79 | |
| 80 | {{ foo.bar }} |
| 81 | |
| 82 | .. note:: |
| 83 | |
| 84 | It's important to know that the curly braces are *not* part of the |
| 85 | variable but the print statement. When accessing variables inside tags, |
| 86 | don't put the braces around them. |
| 87 | |
| 88 | .. sidebar:: Implementation |
| 89 | |
| 90 | For convenience's sake ``foo.bar`` does the following things on the PHP |
| 91 | layer: |
| 92 | |
| 93 | * check if ``foo`` is an array and ``bar`` a valid element; |
| 94 | * if not, and if ``foo`` is an object, check that ``bar`` is a valid property; |
| 95 | * if not, and if ``foo`` is an object, check that ``bar`` is a valid method |
| 96 | (even if ``bar`` is the constructor - use ``__construct()`` instead); |
| 97 | * if not, and if ``foo`` is an object, check that ``getBar`` is a valid method; |
| 98 | * if not, and if ``foo`` is an object, check that ``isBar`` is a valid method; |
| 99 | * if not, and if ``foo`` is an object, check that ``hasBar`` is a valid method; |
| 100 | * if not, return a ``null`` value. |
| 101 | |
| 102 | Twig also supports a specific syntax for accessing items on PHP arrays, |
| 103 | ``foo['bar']``: |
| 104 | |
| 105 | * check if ``foo`` is an array and ``bar`` a valid element; |
| 106 | * if not, return a ``null`` value. |
| 107 | |
| 108 | If a variable or attribute does not exist, you will receive a ``null`` value |
| 109 | when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables`` |
| 110 | is set, Twig will throw an error (see :ref:`environment options<environment_options>`). |
| 111 | |
| 112 | .. note:: |
| 113 | |
| 114 | If you want to access a dynamic attribute of a variable, use the |
| 115 | :doc:`attribute<functions/attribute>` function instead. |
| 116 | |
| 117 | The ``attribute`` function is also useful when the attribute contains |
| 118 | special characters (like ``-`` that would be interpreted as the minus |
| 119 | operator): |
| 120 | |
| 121 | .. code-block:: twig |
| 122 | |
| 123 | {# equivalent to the non-working foo.data-foo #} |
| 124 | {{ attribute(foo, 'data-foo') }} |
| 125 | |
| 126 | Global Variables |
| 127 | ~~~~~~~~~~~~~~~~ |
| 128 | |
| 129 | The following variables are always available in templates: |
| 130 | |
| 131 | * ``_self``: references the current template name; |
| 132 | * ``_context``: references the current context; |
| 133 | * ``_charset``: references the current charset. |
| 134 | |
| 135 | Setting Variables |
| 136 | ~~~~~~~~~~~~~~~~~ |
| 137 | |
| 138 | You can assign values to variables inside code blocks. Assignments use the |
| 139 | :doc:`set<tags/set>` tag: |
| 140 | |
| 141 | .. code-block:: twig |
| 142 | |
| 143 | {% set foo = 'foo' %} |
| 144 | {% set foo = [1, 2] %} |
| 145 | {% set foo = {'foo': 'bar'} %} |
| 146 | |
| 147 | Filters |
| 148 | ------- |
| 149 | |
| 150 | Variables can be modified by **filters**. Filters are separated from the |
| 151 | variable by a pipe symbol (``|``). Multiple filters can be chained. The output |
| 152 | of one filter is applied to the next. |
| 153 | |
| 154 | The following example removes all HTML tags from the ``name`` and title-cases |
| 155 | it: |
| 156 | |
| 157 | .. code-block:: twig |
| 158 | |
| 159 | {{ name|striptags|title }} |
| 160 | |
| 161 | Filters that accept arguments have parentheses around the arguments. This |
| 162 | example joins the elements of a list by commas: |
| 163 | |
| 164 | .. code-block:: twig |
| 165 | |
| 166 | {{ list|join(', ') }} |
| 167 | |
| 168 | To apply a filter on a section of code, wrap it with the |
| 169 | :doc:`apply<tags/apply>` tag: |
| 170 | |
| 171 | .. code-block:: twig |
| 172 | |
| 173 | {% apply upper %} |
| 174 | This text becomes uppercase |
| 175 | {% endapply %} |
| 176 | |
| 177 | Go to the :doc:`filters<filters/index>` page to learn more about built-in |
| 178 | filters. |
| 179 | |
| 180 | Functions |
| 181 | --------- |
| 182 | |
| 183 | Functions can be called to generate content. Functions are called by their |
| 184 | name followed by parentheses (``()``) and may have arguments. |
| 185 | |
| 186 | For instance, the ``range`` function returns a list containing an arithmetic |
| 187 | progression of integers: |
| 188 | |
| 189 | .. code-block:: twig |
| 190 | |
| 191 | {% for i in range(0, 3) %} |
| 192 | {{ i }}, |
| 193 | {% endfor %} |
| 194 | |
| 195 | Go to the :doc:`functions<functions/index>` page to learn more about the |
| 196 | built-in functions. |
| 197 | |
| 198 | .. _named-arguments: |
| 199 | |
| 200 | Named Arguments |
| 201 | --------------- |
| 202 | |
| 203 | .. code-block:: twig |
| 204 | |
| 205 | {% for i in range(low=1, high=10, step=2) %} |
| 206 | {{ i }}, |
| 207 | {% endfor %} |
| 208 | |
| 209 | Using named arguments makes your templates more explicit about the meaning of |
| 210 | the values you pass as arguments: |
| 211 | |
| 212 | .. code-block:: twig |
| 213 | |
| 214 | {{ data|convert_encoding('UTF-8', 'iso-2022-jp') }} |
| 215 | |
| 216 | {# versus #} |
| 217 | |
| 218 | {{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }} |
| 219 | |
| 220 | Named arguments also allow you to skip some arguments for which you don't want |
| 221 | to change the default value: |
| 222 | |
| 223 | .. code-block:: twig |
| 224 | |
| 225 | {# the first argument is the date format, which defaults to the global date format if null is passed #} |
| 226 | {{ "now"|date(null, "Europe/Paris") }} |
| 227 | |
| 228 | {# or skip the format value by using a named argument for the time zone #} |
| 229 | {{ "now"|date(timezone="Europe/Paris") }} |
| 230 | |
| 231 | You can also use both positional and named arguments in one call, in which |
| 232 | case positional arguments must always come before named arguments: |
| 233 | |
| 234 | .. code-block:: twig |
| 235 | |
| 236 | {{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }} |
| 237 | |
| 238 | .. tip:: |
| 239 | |
| 240 | Each function and filter documentation page has a section where the names |
| 241 | of all arguments are listed when supported. |
| 242 | |
| 243 | Control Structure |
| 244 | ----------------- |
| 245 | |
| 246 | A control structure refers to all those things that control the flow of a |
| 247 | program - conditionals (i.e. ``if``/``elseif``/``else``), ``for``-loops, as |
| 248 | well as things like blocks. Control structures appear inside ``{% ... %}`` |
| 249 | blocks. |
| 250 | |
| 251 | For example, to display a list of users provided in a variable called |
| 252 | ``users``, use the :doc:`for<tags/for>` tag: |
| 253 | |
| 254 | .. code-block:: html+twig |
| 255 | |
| 256 | <h1>Members</h1> |
| 257 | <ul> |
| 258 | {% for user in users %} |
| 259 | <li>{{ user.username|e }}</li> |
| 260 | {% endfor %} |
| 261 | </ul> |
| 262 | |
| 263 | The :doc:`if<tags/if>` tag can be used to test an expression: |
| 264 | |
| 265 | .. code-block:: html+twig |
| 266 | |
| 267 | {% if users|length > 0 %} |
| 268 | <ul> |
| 269 | {% for user in users %} |
| 270 | <li>{{ user.username|e }}</li> |
| 271 | {% endfor %} |
| 272 | </ul> |
| 273 | {% endif %} |
| 274 | |
| 275 | Go to the :doc:`tags<tags/index>` page to learn more about the built-in tags. |
| 276 | |
| 277 | Comments |
| 278 | -------- |
| 279 | |
| 280 | To comment-out part of a line in a template, use the comment syntax ``{# ... |
| 281 | #}``. This is useful for debugging or to add information for other template |
| 282 | designers or yourself: |
| 283 | |
| 284 | .. code-block:: twig |
| 285 | |
| 286 | {# note: disabled template because we no longer use this |
| 287 | {% for user in users %} |
| 288 | ... |
| 289 | {% endfor %} |
| 290 | #} |
| 291 | |
| 292 | Including other Templates |
| 293 | ------------------------- |
| 294 | |
| 295 | The :doc:`include<functions/include>` function is useful to include a template |
| 296 | and return the rendered content of that template into the current one: |
| 297 | |
| 298 | .. code-block:: twig |
| 299 | |
| 300 | {{ include('sidebar.html') }} |
| 301 | |
| 302 | By default, included templates have access to the same context as the template |
| 303 | which includes them. This means that any variable defined in the main template |
| 304 | will be available in the included template too: |
| 305 | |
| 306 | .. code-block:: twig |
| 307 | |
| 308 | {% for box in boxes %} |
| 309 | {{ include('render_box.html') }} |
| 310 | {% endfor %} |
| 311 | |
| 312 | The included template ``render_box.html`` is able to access the ``box`` variable. |
| 313 | |
| 314 | The name of the template depends on the template loader. For instance, the |
| 315 | ``\Twig\Loader\FilesystemLoader`` allows you to access other templates by giving the |
| 316 | filename. You can access templates in subdirectories with a slash: |
| 317 | |
| 318 | .. code-block:: twig |
| 319 | |
| 320 | {{ include('sections/articles/sidebar.html') }} |
| 321 | |
| 322 | This behavior depends on the application embedding Twig. |
| 323 | |
| 324 | Template Inheritance |
| 325 | -------------------- |
| 326 | |
| 327 | The most powerful part of Twig is template inheritance. Template inheritance |
| 328 | allows you to build a base "skeleton" template that contains all the common |
| 329 | elements of your site and defines **blocks** that child templates can |
| 330 | override. |
| 331 | |
| 332 | It's easier to understand the concept by starting with an example. |
| 333 | |
| 334 | Let's define a base template, ``base.html``, which defines an HTML skeleton |
| 335 | document that might be used for a two-column page: |
| 336 | |
| 337 | .. code-block:: html+twig |
| 338 | |
| 339 | <!DOCTYPE html> |
| 340 | <html> |
| 341 | <head> |
| 342 | {% block head %} |
| 343 | <link rel="stylesheet" href="style.css"/> |
| 344 | <title>{% block title %}{% endblock %} - My Webpage</title> |
| 345 | {% endblock %} |
| 346 | </head> |
| 347 | <body> |
| 348 | <div id="content">{% block content %}{% endblock %}</div> |
| 349 | <div id="footer"> |
| 350 | {% block footer %} |
| 351 | © Copyright 2011 by <a href="http://domain.invalid/">you</a>. |
| 352 | {% endblock %} |
| 353 | </div> |
| 354 | </body> |
| 355 | </html> |
| 356 | |
| 357 | In this example, the :doc:`block<tags/block>` tags define four blocks that |
| 358 | child templates can fill in. All the ``block`` tag does is to tell the |
| 359 | template engine that a child template may override those portions of the |
| 360 | template. |
| 361 | |
| 362 | A child template might look like this: |
| 363 | |
| 364 | .. code-block:: html+twig |
| 365 | |
| 366 | {% extends "base.html" %} |
| 367 | |
| 368 | {% block title %}Index{% endblock %} |
| 369 | {% block head %} |
| 370 | {{ parent() }} |
| 371 | <style type="text/css"> |
| 372 | .important { color: #336699; } |
| 373 | </style> |
| 374 | {% endblock %} |
| 375 | {% block content %} |
| 376 | <h1>Index</h1> |
| 377 | <p class="important"> |
| 378 | Welcome to my awesome homepage. |
| 379 | </p> |
| 380 | {% endblock %} |
| 381 | |
| 382 | The :doc:`extends<tags/extends>` tag is the key here. It tells the template |
| 383 | engine that this template "extends" another template. When the template system |
| 384 | evaluates this template, first it locates the parent. The extends tag should |
| 385 | be the first tag in the template. |
| 386 | |
| 387 | Note that since the child template doesn't define the ``footer`` block, the |
| 388 | value from the parent template is used instead. |
| 389 | |
| 390 | It's possible to render the contents of the parent block by using the |
| 391 | :doc:`parent<functions/parent>` function. This gives back the results of the |
| 392 | parent block: |
| 393 | |
| 394 | .. code-block:: html+twig |
| 395 | |
| 396 | {% block sidebar %} |
| 397 | <h3>Table Of Contents</h3> |
| 398 | ... |
| 399 | {{ parent() }} |
| 400 | {% endblock %} |
| 401 | |
| 402 | .. tip:: |
| 403 | |
| 404 | The documentation page for the :doc:`extends<tags/extends>` tag describes |
| 405 | more advanced features like block nesting, scope, dynamic inheritance, and |
| 406 | conditional inheritance. |
| 407 | |
| 408 | .. note:: |
| 409 | |
| 410 | Twig also supports multiple inheritance via "horizontal reuse" with the help |
| 411 | of the :doc:`use<tags/use>` tag. |
| 412 | |
| 413 | HTML Escaping |
| 414 | ------------- |
| 415 | |
| 416 | When generating HTML from templates, there's always a risk that a variable |
| 417 | will include characters that affect the resulting HTML. There are two |
| 418 | approaches: manually escaping each variable or automatically escaping |
| 419 | everything by default. |
| 420 | |
| 421 | Twig supports both, automatic escaping is enabled by default. |
| 422 | |
| 423 | The automatic escaping strategy can be configured via the |
| 424 | :ref:`autoescape<environment_options>` option and defaults to ``html``. |
| 425 | |
| 426 | Working with Manual Escaping |
| 427 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 428 | |
| 429 | If manual escaping is enabled, it is **your** responsibility to escape variables |
| 430 | if needed. What to escape? Any variable that comes from an untrusted source. |
| 431 | |
| 432 | Escaping works by using the :doc:`escape<filters/escape>` or ``e`` filter: |
| 433 | |
| 434 | .. code-block:: twig |
| 435 | |
| 436 | {{ user.username|e }} |
| 437 | |
| 438 | By default, the ``escape`` filter uses the ``html`` strategy, but depending on |
| 439 | the escaping context, you might want to explicitly use an other strategy: |
| 440 | |
| 441 | .. code-block:: twig |
| 442 | |
| 443 | {{ user.username|e('js') }} |
| 444 | {{ user.username|e('css') }} |
| 445 | {{ user.username|e('url') }} |
| 446 | {{ user.username|e('html_attr') }} |
| 447 | |
| 448 | Working with Automatic Escaping |
| 449 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 450 | |
| 451 | Whether automatic escaping is enabled or not, you can mark a section of a |
| 452 | template to be escaped or not by using the :doc:`autoescape<tags/autoescape>` |
| 453 | tag: |
| 454 | |
| 455 | .. code-block:: twig |
| 456 | |
| 457 | {% autoescape %} |
| 458 | Everything will be automatically escaped in this block (using the HTML strategy) |
| 459 | {% endautoescape %} |
| 460 | |
| 461 | By default, auto-escaping uses the ``html`` escaping strategy. If you output |
| 462 | variables in other contexts, you need to explicitly escape them with the |
| 463 | appropriate escaping strategy: |
| 464 | |
| 465 | .. code-block:: twig |
| 466 | |
| 467 | {% autoescape 'js' %} |
| 468 | Everything will be automatically escaped in this block (using the JS strategy) |
| 469 | {% endautoescape %} |
| 470 | |
| 471 | Escaping |
| 472 | -------- |
| 473 | |
| 474 | It is sometimes desirable or even necessary to have Twig ignore parts it would |
| 475 | otherwise handle as variables or blocks. For example if the default syntax is |
| 476 | used and you want to use ``{{`` as raw string in the template and not start a |
| 477 | variable you have to use a trick. |
| 478 | |
| 479 | The easiest way is to output the variable delimiter (``{{``) by using a variable |
| 480 | expression: |
| 481 | |
| 482 | .. code-block:: twig |
| 483 | |
| 484 | {{ '{{' }} |
| 485 | |
| 486 | For bigger sections it makes sense to mark a block |
| 487 | :doc:`verbatim<tags/verbatim>`. |
| 488 | |
| 489 | Macros |
| 490 | ------ |
| 491 | |
| 492 | Macros are comparable with functions in regular programming languages. They are |
| 493 | useful to reuse HTML fragments to not repeat yourself. They are described in the |
| 494 | :doc:`macro<tags/macro>` tag documentation. |
| 495 | |
| 496 | .. _twig-expressions: |
| 497 | |
| 498 | Expressions |
| 499 | ----------- |
| 500 | |
| 501 | Twig allows expressions everywhere. |
| 502 | |
| 503 | .. note:: |
| 504 | |
| 505 | The operator precedence is as follows, with the lowest-precedence operators |
| 506 | listed first: ``?:`` (ternary operator), ``b-and``, ``b-xor``, ``b-or``, |
| 507 | ``or``, ``and``, ``==``, ``!=``, ``<=>``, ``<``, ``>``, ``>=``, ``<=``, |
| 508 | ``in``, ``matches``, ``starts with``, ``ends with``, ``..``, ``+``, ``-``, |
| 509 | ``~``, ``*``, ``/``, ``//``, ``%``, ``is`` (tests), ``**``, ``??``, ``|`` |
| 510 | (filters), ``[]``, and ``.``: |
| 511 | |
| 512 | .. code-block:: twig |
| 513 | |
| 514 | {% set greeting = 'Hello ' %} |
| 515 | {% set name = 'Fabien' %} |
| 516 | |
| 517 | {{ greeting ~ name|lower }} {# Hello fabien #} |
| 518 | |
| 519 | {# use parenthesis to change precedence #} |
| 520 | {{ (greeting ~ name)|lower }} {# hello fabien #} |
| 521 | |
| 522 | Literals |
| 523 | ~~~~~~~~ |
| 524 | |
| 525 | The simplest form of expressions are literals. Literals are representations |
| 526 | for PHP types such as strings, numbers, and arrays. The following literals |
| 527 | exist: |
| 528 | |
| 529 | * ``"Hello World"``: Everything between two double or single quotes is a |
| 530 | string. They are useful whenever you need a string in the template (for |
| 531 | example as arguments to function calls, filters or just to extend or include |
| 532 | a template). A string can contain a delimiter if it is preceded by a |
| 533 | backslash (``\``) -- like in ``'It\'s good'``. If the string contains a |
| 534 | backslash (e.g. ``'c:\Program Files'``) escape it by doubling it |
| 535 | (e.g. ``'c:\\Program Files'``). |
| 536 | |
| 537 | * ``42`` / ``42.23``: Integers and floating point numbers are created by |
| 538 | writing the number down. If a dot is present the number is a float, |
| 539 | otherwise an integer. |
| 540 | |
| 541 | * ``["foo", "bar"]``: Arrays are defined by a sequence of expressions |
| 542 | separated by a comma (``,``) and wrapped with squared brackets (``[]``). |
| 543 | |
| 544 | * ``{"foo": "bar"}``: Hashes are defined by a list of keys and values |
| 545 | separated by a comma (``,``) and wrapped with curly braces (``{}``): |
| 546 | |
| 547 | .. code-block:: twig |
| 548 | |
| 549 | {# keys as string #} |
| 550 | { 'foo': 'foo', 'bar': 'bar' } |
| 551 | |
| 552 | {# keys as names (equivalent to the previous hash) #} |
| 553 | { foo: 'foo', bar: 'bar' } |
| 554 | |
| 555 | {# keys as integer #} |
| 556 | { 2: 'foo', 4: 'bar' } |
| 557 | |
| 558 | {# keys can be omitted if it is the same as the variable name #} |
| 559 | { foo } |
| 560 | {# is equivalent to the following #} |
| 561 | { 'foo': foo } |
| 562 | |
| 563 | {# keys as expressions (the expression must be enclosed into parentheses) #} |
| 564 | {% set foo = 'foo' %} |
| 565 | { (foo): 'foo', (1 + 1): 'bar', (foo ~ 'b'): 'baz' } |
| 566 | |
| 567 | * ``true`` / ``false``: ``true`` represents the true value, ``false`` |
| 568 | represents the false value. |
| 569 | |
| 570 | * ``null``: ``null`` represents no specific value. This is the value returned |
| 571 | when a variable does not exist. ``none`` is an alias for ``null``. |
| 572 | |
| 573 | Arrays and hashes can be nested: |
| 574 | |
| 575 | .. code-block:: twig |
| 576 | |
| 577 | {% set foo = [1, {"foo": "bar"}] %} |
| 578 | |
| 579 | .. tip:: |
| 580 | |
| 581 | Using double-quoted or single-quoted strings has no impact on performance |
| 582 | but :ref:`string interpolation <templates-string-interpolation>` is only |
| 583 | supported in double-quoted strings. |
| 584 | |
| 585 | Math |
| 586 | ~~~~ |
| 587 | |
| 588 | Twig allows you to do math in templates; the following operators are supported: |
| 589 | |
| 590 | * ``+``: Adds two numbers together (the operands are casted to numbers). ``{{ |
| 591 | 1 + 1 }}`` is ``2``. |
| 592 | |
| 593 | * ``-``: Subtracts the second number from the first one. ``{{ 3 - 2 }}`` is |
| 594 | ``1``. |
| 595 | |
| 596 | * ``/``: Divides two numbers. The returned value will be a floating point |
| 597 | number. ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``. |
| 598 | |
| 599 | * ``%``: Calculates the remainder of an integer division. ``{{ 11 % 7 }}`` is |
| 600 | ``4``. |
| 601 | |
| 602 | * ``//``: Divides two numbers and returns the floored integer result. ``{{ 20 |
| 603 | // 7 }}`` is ``2``, ``{{ -20 // 7 }}`` is ``-3`` (this is just syntactic |
| 604 | sugar for the :doc:`round<filters/round>` filter). |
| 605 | |
| 606 | * ``*``: Multiplies the left operand with the right one. ``{{ 2 * 2 }}`` would |
| 607 | return ``4``. |
| 608 | |
| 609 | * ``**``: Raises the left operand to the power of the right operand. ``{{ 2 ** |
| 610 | 3 }}`` would return ``8``. |
| 611 | |
| 612 | .. _template_logic: |
| 613 | |
| 614 | Logic |
| 615 | ~~~~~ |
| 616 | |
| 617 | You can combine multiple expressions with the following operators: |
| 618 | |
| 619 | * ``and``: Returns true if the left and the right operands are both true. |
| 620 | |
| 621 | * ``or``: Returns true if the left or the right operand is true. |
| 622 | |
| 623 | * ``not``: Negates a statement. |
| 624 | |
| 625 | * ``(expr)``: Groups an expression. |
| 626 | |
| 627 | .. note:: |
| 628 | |
| 629 | Twig also supports bitwise operators (``b-and``, ``b-xor``, and ``b-or``). |
| 630 | |
| 631 | .. note:: |
| 632 | |
| 633 | Operators are case sensitive. |
| 634 | |
| 635 | Comparisons |
| 636 | ~~~~~~~~~~~ |
| 637 | |
| 638 | The following comparison operators are supported in any expression: ``==``, |
| 639 | ``!=``, ``<``, ``>``, ``>=``, and ``<=``. |
| 640 | |
| 641 | You can also check if a string ``starts with`` or ``ends with`` another |
| 642 | string: |
| 643 | |
| 644 | .. code-block:: twig |
| 645 | |
| 646 | {% if 'Fabien' starts with 'F' %} |
| 647 | {% endif %} |
| 648 | |
| 649 | {% if 'Fabien' ends with 'n' %} |
| 650 | {% endif %} |
| 651 | |
| 652 | .. note:: |
| 653 | |
| 654 | For complex string comparisons, the ``matches`` operator allows you to use |
| 655 | `regular expressions`_: |
| 656 | |
| 657 | .. code-block:: twig |
| 658 | |
| 659 | {% if phone matches '/^[\\d\\.]+$/' %} |
| 660 | {% endif %} |
| 661 | |
| 662 | Containment Operator |
| 663 | ~~~~~~~~~~~~~~~~~~~~ |
| 664 | |
| 665 | The ``in`` operator performs containment test. It returns ``true`` if the left |
| 666 | operand is contained in the right: |
| 667 | |
| 668 | .. code-block:: twig |
| 669 | |
| 670 | {# returns true #} |
| 671 | |
| 672 | {{ 1 in [1, 2, 3] }} |
| 673 | |
| 674 | {{ 'cd' in 'abcde' }} |
| 675 | |
| 676 | .. tip:: |
| 677 | |
| 678 | You can use this filter to perform a containment test on strings, arrays, |
| 679 | or objects implementing the ``Traversable`` interface. |
| 680 | |
| 681 | To perform a negative test, use the ``not in`` operator: |
| 682 | |
| 683 | .. code-block:: twig |
| 684 | |
| 685 | {% if 1 not in [1, 2, 3] %} |
| 686 | |
| 687 | {# is equivalent to #} |
| 688 | {% if not (1 in [1, 2, 3]) %} |
| 689 | |
| 690 | Test Operator |
| 691 | ~~~~~~~~~~~~~ |
| 692 | |
| 693 | The ``is`` operator performs tests. Tests can be used to test a variable against |
| 694 | a common expression. The right operand is name of the test: |
| 695 | |
| 696 | .. code-block:: twig |
| 697 | |
| 698 | {# find out if a variable is odd #} |
| 699 | |
| 700 | {{ name is odd }} |
| 701 | |
| 702 | Tests can accept arguments too: |
| 703 | |
| 704 | .. code-block:: twig |
| 705 | |
| 706 | {% if post.status is constant('Post::PUBLISHED') %} |
| 707 | |
| 708 | Tests can be negated by using the ``is not`` operator: |
| 709 | |
| 710 | .. code-block:: twig |
| 711 | |
| 712 | {% if post.status is not constant('Post::PUBLISHED') %} |
| 713 | |
| 714 | {# is equivalent to #} |
| 715 | {% if not (post.status is constant('Post::PUBLISHED')) %} |
| 716 | |
| 717 | Go to the :doc:`tests<tests/index>` page to learn more about the built-in |
| 718 | tests. |
| 719 | |
| 720 | Other Operators |
| 721 | ~~~~~~~~~~~~~~~ |
| 722 | |
| 723 | The following operators don't fit into any of the other categories: |
| 724 | |
| 725 | * ``|``: Applies a filter. |
| 726 | |
| 727 | * ``..``: Creates a sequence based on the operand before and after the operator |
| 728 | (this is syntactic sugar for the :doc:`range<functions/range>` function): |
| 729 | |
| 730 | .. code-block:: twig |
| 731 | |
| 732 | {{ 1..5 }} |
| 733 | |
| 734 | {# equivalent to #} |
| 735 | {{ range(1, 5) }} |
| 736 | |
| 737 | Note that you must use parentheses when combining it with the filter operator |
| 738 | due to the :ref:`operator precedence rules <twig-expressions>`: |
| 739 | |
| 740 | .. code-block:: twig |
| 741 | |
| 742 | (1..5)|join(', ') |
| 743 | |
| 744 | * ``~``: Converts all operands into strings and concatenates them. ``{{ "Hello |
| 745 | " ~ name ~ "!" }}`` would return (assuming ``name`` is ``'John'``) ``Hello |
| 746 | John!``. |
| 747 | |
| 748 | * ``.``, ``[]``: Gets an attribute of a variable. |
| 749 | |
| 750 | * ``?:``: The ternary operator: |
| 751 | |
| 752 | .. code-block:: twig |
| 753 | |
| 754 | {{ foo ? 'yes' : 'no' }} |
| 755 | {{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }} |
| 756 | {{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }} |
| 757 | |
| 758 | * ``??``: The null-coalescing operator: |
| 759 | |
| 760 | .. code-block:: twig |
| 761 | |
| 762 | {# returns the value of foo if it is defined and not null, 'no' otherwise #} |
| 763 | {{ foo ?? 'no' }} |
| 764 | |
| 765 | .. _templates-string-interpolation: |
| 766 | |
| 767 | String Interpolation |
| 768 | ~~~~~~~~~~~~~~~~~~~~ |
| 769 | |
| 770 | String interpolation (``#{expression}``) allows any valid expression to appear |
| 771 | within a *double-quoted string*. The result of evaluating that expression is |
| 772 | inserted into the string: |
| 773 | |
| 774 | .. code-block:: twig |
| 775 | |
| 776 | {{ "foo #{bar} baz" }} |
| 777 | {{ "foo #{1 + 2} baz" }} |
| 778 | |
| 779 | .. _templates-whitespace-control: |
| 780 | |
| 781 | Whitespace Control |
| 782 | ------------------ |
| 783 | |
| 784 | The first newline after a template tag is removed automatically (like in PHP). |
| 785 | Whitespace is not further modified by the template engine, so each whitespace |
| 786 | (spaces, tabs, newlines etc.) is returned unchanged. |
| 787 | |
| 788 | You can also control whitespace on a per tag level. By using the whitespace |
| 789 | control modifiers on your tags, you can trim leading and or trailing whitespace. |
| 790 | |
| 791 | Twig supports two modifiers: |
| 792 | |
| 793 | * *Whitespace trimming* via the ``-`` modifier: Removes all whitespace |
| 794 | (including newlines); |
| 795 | |
| 796 | * *Line whitespace trimming* via the ``~`` modifier: Removes all whitespace |
| 797 | (excluding newlines). Using this modifier on the right disables the default |
| 798 | removal of the first newline inherited from PHP. |
| 799 | |
| 800 | The modifiers can be used on either side of the tags like in ``{%-`` or ``-%}`` |
| 801 | and they consume all whitespace for that side of the tag. It is possible to use |
| 802 | the modifiers on one side of a tag or on both sides: |
| 803 | |
| 804 | .. code-block:: html+twig |
| 805 | |
| 806 | {% set value = 'no spaces' %} |
| 807 | {#- No leading/trailing whitespace -#} |
| 808 | {%- if true -%} |
| 809 | {{- value -}} |
| 810 | {%- endif -%} |
| 811 | {# output 'no spaces' #} |
| 812 | |
| 813 | <li> |
| 814 | {{ value }} </li> |
| 815 | {# outputs '<li>\n no spaces </li>' #} |
| 816 | |
| 817 | <li> |
| 818 | {{- value }} </li> |
| 819 | {# outputs '<li>no spaces </li>' #} |
| 820 | |
| 821 | <li> |
| 822 | {{~ value }} </li> |
| 823 | {# outputs '<li>\nno spaces </li>' #} |
| 824 | |
| 825 | .. tip:: |
| 826 | |
| 827 | In addition to the whitespace modifiers, Twig also has a ``spaceless`` filter |
| 828 | that removes whitespace **between HTML tags**: |
| 829 | |
| 830 | .. code-block:: html+twig |
| 831 | |
| 832 | {% apply spaceless %} |
| 833 | <div> |
| 834 | <strong>foo bar</strong> |
| 835 | </div> |
| 836 | {% endapply %} |
| 837 | |
| 838 | {# output will be <div><strong>foo bar</strong></div> #} |
| 839 | |
| 840 | Extensions |
| 841 | ---------- |
| 842 | |
| 843 | Twig can be extended. If you want to create your own extensions, read the |
| 844 | :ref:`Creating an Extension <creating_extensions>` chapter. |
| 845 | |
| 846 | .. _`Twig bundle`: https://github.com/Anomareh/PHP-Twig.tmbundle |
| 847 | .. _`Jinja syntax plugin`: http://jinja.pocoo.org/docs/integration/#vim |
| 848 | .. _`vim-twig plugin`: https://github.com/lumiliet/vim-twig |
| 849 | .. _`Twig syntax plugin`: http://plugins.netbeans.org/plugin/37069/php-twig |
| 850 | .. _`Twig plugin`: https://github.com/pulse00/Twig-Eclipse-Plugin |
| 851 | .. _`Twig language definition`: https://github.com/gabrielcorpse/gedit-twig-template-language |
| 852 | .. _`Twig syntax mode`: https://github.com/bobthecow/Twig-HTML.mode |
| 853 | .. _`other Twig syntax mode`: https://github.com/muxx/Twig-HTML.mode |
| 854 | .. _`Notepad++ Twig Highlighter`: https://github.com/Banane9/notepadplusplus-twig |
| 855 | .. _`web-mode.el`: http://web-mode.org/ |
| 856 | .. _`regular expressions`: https://secure.php.net/manual/en/pcre.pattern.php |
| 857 | .. _`PHP-twig for atom`: https://github.com/reesef/php-twig |
| 858 | .. _`TwigFiddle`: https://twigfiddle.com/ |
| 859 | .. _`Twig pack`: https://marketplace.visualstudio.com/items?itemName=bajdzis.vscode-twig-pack |