SlideShare uma empresa Scribd logo
1 de 114
Baixar para ler offline
Making Sense
of Twig
Brandon Kelly
What is Twig?
It’s a templating language.
!
All templating features are
available globally to all
templates in any context,
as part of the language.
!
It’s not up to each and every
application feature to
provide its own tags.
It’s super powerful.
!
- Many ways to stay DRY
- Custom variables
- Functions
- Filters
- It knows math
- Whitespace control
- Extensible
Templates get compiled into
PHP, so it’s super fast.
Twig even makes debugging a
piece of cake.
Used by some popular apps:
!
- LemonStand
- Symfony
- Craft
- others
twig.sensiolabs.org
The Language
Types of Tags
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
{% block main %}
<p>Hey!</p>
{% endblock %}
</body>
</html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
{% block main %}
<p>Hey!</p>
{% endblock %}
</body>
</html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
{% block main %}
<p>Hey!</p>
{% endblock %}
</body>
</html>
Twig code always lives
within one of these three
tag pairs:
!
{# ... #}
{{ ... }}
{% ... %}
{# ... #}
Comment Tags
Comment tags are like HTML
comments, except they won’t
show up in the page source.
!
{# This won’t make it to
the page source #}
!
<!-- This will -->
{{ ... }}
Output Tags
Output tags output stuff to
the browser.
!
{{ title }}
!
{{ "Howdy" }}
!
{{ 84 / 2 }}
{% ... %}
Logic Tags
Logic tags (or just “tags”)
control the logic of the
template:
!
- Conditionals
- Loops
- Variable definitions
- Macros
- Template includes
- etc.
The syntax varies from tag
to tag.
Some are just a single word.
!
{% requireLogin %}
Some take parameters.
!
{% exit 404 %}
Some have a closing tag.
!
{% block content %}
<p>Hey</p>
{% endblock %}
Some even have nested tags.
!
{% if foo %}
<p>Something</p>
{% else %}
<p>Something else</p>
{% endif %}
It really all depends on
the tag.
!
The only thing they have in
common is that they all start
with “{%”, followed by the
tag name.
!
{% tagname ...
Twig comes with several
built-in tags.
!
{% autoescape %}
{% block %}
{% filter %}
{% do %}
{% embed %}
{% extends %}
{% autoescape %}
{% flush %}
{% for %}
{% from %}
{% if %}
{% import %}
{% include %}
{% macro %}
{% sandbox %}
{% set %}
{% spaceless %}
{% use %}
{% verbatim %}
{% autoescape %}
!
Escapes text for HTML.
!
{% autoescape %}
<p>Hey</p>
{% endautoescape %}
=> &lt;p&gt;Hey&lt;/p&gt;
{% autoescape %} (Cont.)
!
...or Javascript
!
{% autoescape "js" %}
http://foo.com
{% endautoescape %}
=> httpx3Ax2Fx2Ffoo.com
{% spaceless %}
!
Removes any whitespace
between Twig/HTML tags.
!
{%- spaceless %}
<p>Hey there</p>
{% endspaceless -%}
=> <p>Hey there</p>
{% verbatim %}
!
Defines template code that
Twig should output as-is,
without parsing.
!
{% verbatim %}
<p>Type “{{ foo }}”.</p>
{% endverbatim %}
=> <p>Type “{{ foo }}”.</p>
You never put a Twig tag
inside another Twig tag.
!
Bad:
!
{{ "Hey {{ firstName }}" }}
!
Good:
!
{{ "Hey " ~ firstName }}
Values, Expressions,

and Variables
Twig supports five different
types of values.
!
Strings: "Hey" / 'Hey'
Numbers: 42 / 3.14
Booleans: true / false
Arrays: ['a', 'b', 'c']
Objects: { foo: 'bar' }
An expression is either a solo
value, or multiple values
combined to form another value.
!
"Hey" => "Hey"
"Hey "~"there" => "Hey there"
10 => 10
true => true
['a','b','c'] => ['a','b','c']
"Day "~1 => "Day 1"
10*(5+5) => 100
Variables are values that get
set to a name, to be
referenced later.
!
Use the {% set %} tag to
create them.
!
{% set foo = "foo" %}
{% set a = 42 %}
{% set foobar = foo~"bar" %}
The {% set %} tag can also be
used as a tag pair.
!
{% set foo %}
<p>foo</p>
{% endset %}
!
That’s the same as:
!
{% set foo = "n
<p>foo</p>n
" %}
Variables are one tool for
keeping our templates DRY.
!
{% set title = "About Us" %}
...
<title>{{ title }}</title>
...
<h1>{{ title }}</h1>
Filters
Filters modify values.
!
They can uppercase text,
merge arrays, and lots of
other things.
To pass a value through a
filter, type a pipe (“|”)
after the value, followed by
the filter name.
!
"foo"|upper => "FOO"
21.3|round => 21
['a','b','c']|length => 3
Some accept arguments.
!
"foobar"|slice(0,3)
=> foo
You can even chain them.
!
"foobar"|slice(0,3)|upper
=> FOO
You can add filters to
variables, too.
!
{% set foo = "foo" %}
{{ foo|length }}
=> 3
You can use them in pretty
much any context you can
think of.
!
{{ value|filter }}
!
{% set foo = value|filter %}
!
{% do func(value|filter) %}
Filters only modify the value
directly before the filter.
!
"foo"~"bar"|upper
=> fooBAR
!
("foo"~"bar")|upper
=> FOOBAR
Twig comes with tons of
built-in filters:
|abs
|batch
|capitalize
|covert_encoding
|date
|date_modify
|default
|escape
|first
|format
|join
|json_encode
|keys
|last
|length
|lower
|nl2br
|number_format
|merge
|upper
|raw
|replace
|reverse
|round
|slice
|sort
|split
|striptags
|title
|trim
|url_encode
|length
!
Finds the length of a string
or array.
!
{{ "foobar"|length }}
=> 6
!
{{ [1, 2, 3]|length }}
=> 3
|upper & |lower
!
Modify the casing of a
string.
!
{{ "foo"|upper }}
=> FOO
!
{{ "BAR"|lower }}
=> bar
|raw
!
Protects a string from
getting escaped.
!
{{ "<p>Hey</p>" }}
=> &lt;p&gt;Hey&lt;/&gt;
!
{{ "<p>Hey</p>"|raw }}
=> <p>Hey</p>
|date
!
Formats a date.
!
{{ now|date("F j, Y") }}
=> April 23, 2014
Functions
Functions perform functions.
!
To call one, type its name,
followed by parentheses.
!
{{ parent() }}
Many functions accept
arguments:
!
random(1, 10)
Some of them are global:
!
{{ dump(foo) }}
!
And they can also be nested
within objects:
!
{{ craft.isLocalized() }}
Twig comes with a few global
functions built-in:
attribute()
block()
constant()
cycle()
date()
dump()
include()
max()
min()
parent()
random()
range()
source()
template_from_string()
min() & max()
!
Returns the smallest/largest
value in a given array.
!
{{ min([1, 2, 3]) }}
=> 1
!
{{ max([1, 2, 3]) }}
=> 3
random()
!
{{ random("foobar") }}
=> f/o/b/a/r
!
{{ random([1, 2, 3]) }}
=> 1/2/3
!
{{ random(10) }}
=> 1/2/3/4/5/6/7/8/9/10
range()
!
Creates a range of numbers as
an array.
!
{% set r = range(1, 5) %}
=> [1, 2, 3, 4, 5]
!
{% set r = [1..5] %}
=> [1, 2, 3, 4, 5]
dump()
!
Outputs information about a
given variable. Helpful when
debugging.
!
{{ dump(foo) }}
!
(In Craft, dump() is only
available in Dev Mode.)
Conditionals
You can prevent certain parts
of your template from
executing unless a certain
condition is met by wrapping
it in conditional tags.
Conditionals always open with
an {% if %} tag, and close
with an {% endif %} tag.
!
{% if user %}
<p>Hey there handsome!</p>
{% endif %}
You can also specify template
code to be executed if the
condition doesn’t pass, using
the {% else %} tag.
!
{% if user %}
<p>Hey there handsome!</p>
{% else %}
<p>Have we met?</p>
{% endif %}
There’s also an {% elseif %} tag
if you need fallback conditions.
!
{% if user %}
<p>Hey there handsome!</p>
{% elseif username %}
<p>Is this {{ username }}?</p>
{% else %}
<p>Have we met?</p>
{% endif %}
Conditionals can be nested.
!
{% if user %}
{% if user.male %}
<p>Hey there handsome!</p>
{% else %}
<p>Hey pretty lady!</p>
{% endif %}
{% elseif username %}
<p>Is this {{ username }}?</p>
{% else %}
<p>Have we met?</p>
{% endif %}
A single condition can be
made up of multiple
expressions joined together
with “and” or “or”.
!
{% if foo and bar %}
!
{% if foo or bar %}
You can negate a condition by
typing “not” before it.
!
{% if not foo %}
You can also group
expressions together using
parentheses.
!
{% if foo and (
foo == "foo" or
foo == "bar"
) %}
Tests
Tests are little conditional
helpers. They don’t have to
be used within conditionals,
but usually are.
To write a test, add either
“is” or “is not” after a
variable, followed by the
test name.
!
{% if foo is defined %}
!
{% if foo is not empty %}
Twig comes with a few tests
built-in.
!
is constant
is defined
is divisible by
is empty
is even
is iterable
is null
is odd
is same as
is defined
!
Tests whether a variable
exists at all, without Twig
getting mad at you if
it’s not.
!
{% if foo is defined %}
is divisible by
!
Tests whether a number is
divisible by another.
!
{% if 5 is divisible by(2) %}
!
That’s similar to writing:
!
{% if 5 % 2 == 0 %}
is even & is odd
!
Tests whether a number is
even/odd.
!
{% if 5 is even %}
!
{% if 5 is odd %}
is empty
!
Tests whether a variable is
“empty”.
!
{% if foo is not empty %}
!
That’s the same as writing:
!
{% if foo %}
is same as
!
Tests whether two variables
have the same *type*.
!
{% if 5 == "5" %}
=> true
!
{% if 5 is same as "5" %}
=> false
Working with
Arrays and Objects
Arrays and objects both
contain multiple values.
Arrays contain values in a
specific order, and have an
inherent numerical index.
!
{% set arr = ['a','b','c'] %}
!
{{ arr[0] }} => 'a'
{{ arr[1] }} => 'b'
{{ arr[2] }} => 'c'
Objects contain key-value
pairs, and the order is
generally less important.
!
{% set obj = {
foo: "Foo",
bar: "Bar"
} %}
!
{{ obj.foo }} => "Foo"
{{ obj.bar }} => "Bar"
You can merge arrays together
with the ‘merge’ filter.
!
{% set a1 = ['a','b'] %}
{% set a2 = ['c','d'] %}
{% set a3 = a1|merge(a2) %}
!
=> ['a','b','c','d']
You can merge objects
together too.
!
{% set o1 = {foo: "Foo"} %}
{% set o2 = {bar: "Bar"} %}
{% set o3 = o1|merge(o2) %}
!
=> {foo: "Foo", bar: "Bar"}
You can grab part of an array
with the “slice” filter.
!
{% set a1 = ['a','b','c'] %}
{% set a2 = a1|slice(0, 2) %}
!
=> ['a','b']
!
A shortcut is also available:
!
{% set a2 = a1[0:2] %}
Looping through

arrays and objects
You can loop through arrays with
the {% for %} tag.
!
The syntax is:
!
{% for itemname in myarray %}
...
{% endfor %}
!
The 2nd param (“itemname”) is
whatever you want to call each
item within the array.
Example 1: Age field
!
<select name="age">
{% for age in [0..150] %}
<option>
{{ age }}</option>
{% endfor %}
</select>
Example 2: Exp. Year field
!
{% set y1 = now.year %}
{% set y2 = y1 + 10 %}
!
<select name="exp_year">
{% for year in [y1..y2] %}
<option>
{{ year }}</option>
{% endfor %}
</select>
Example 3: Navigation
!
{% set nav = [
{ title: "Home", uri: "" },
{ title: "About", uri: "about" }
] %}
!
<nav>
{% for item in nav %}
<a href="{{ url(item.uri) }}">
{{ item.title }}</a>
{% endfor %}
</nav>
DRY Templating
Includes
Templates can include others.
Include
Template
Parent
Template
Parent
Template
Use the {% include %} tag to
include another template
wherever the tag is placed.
!
{% include "some/template" %}
By default, any variables
available to the “parent”
template will also be available
in the included template.
!
{% set foo = "foo" %}
{% include "myinclude" %}
!
myinclude.html:
{{ foo }}
=> foo
You can define additional
variables just for the included
template using the “with” param.
!
{% include "myinclude"
with { foo: "foo" }
%}
!
some/template.html:
{{ foo }}
=> foo
To *only* pass certain variables
to the included template, use the
“only” param.
!
{% set foo = "foo" %}
{% include "myinclude"
with { bar: "bar" } only
%}
!
some/template.html:
{% if foo is defined %}
=> false
Extending Templates
A template can extend
another, overriding parts of
it (called “blocks”).
Parent Template
Block
Child Template Child Template
Define overridable areas in
the parent template using the
{% block %} tag.
!
<body>
{% block body %}
<p>Default content</p>
{% endblock %}
</body>
Use the {% extends %} tag
within your child template to
tell it which template it
extends.
!
{% extends "layout" %}
Override the parent’s blocks
by creating new blocks in the
child template with the same
name.
!
{% extends "layout" %}
!
{% block body %}
<p>Override content</p>
{% endblock %}
You can output the parent
block’s content using the
parent() function.
!
{% extends "layout" %}
!
{% block body %}
{{ parent() }}
<p>Additional content</p>
{% endblock %}
Multi-level inheritance is
totally possible.
Embedding Templates
Twig also lets you “embed”
other templates, which is
similar to including them,
except you get to override
the child template’s blocks
in the process.
Making Sense of Twig
Use the {% embed %} tag to
embed another template.
!
{% embed "promo" %}
{% block body %}
{{ parent() }}
<span class="ribbon">
50% off!
</span>
{% endblock %}
{% endembed %}
Macros
Macros are like includes that
are defined right within
another template.
Use the {% macro %} tag to
define them.
!
{% macro errors(list) %}
{% if list|length %}
<ul class="errors">
{% for error in list %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
You must import macros before
you can use them, with either
{% from %} or {% import %}.
!
{% from _self import errors %}
{{ errors(entry.allErrors) }}
!
!
{% import _self as m %}
{{ m.errors(entry.allErrors) }}
You can import macros from other
templates, too.
!
{% from "macros" import errors %}
{{ errors(entry.allErrors) }}
!
!
{% import "macros" as m %}
{{ m.errors(entry.allErrors) }}
!
The End.

Mais conteúdo relacionado

Mais procurados

Mais procurados (20)

Apache Velocity 1.6
Apache Velocity 1.6Apache Velocity 1.6
Apache Velocity 1.6
 
Php string function
Php string function Php string function
Php string function
 
Open Source Package PHP & MySQL
Open Source Package PHP & MySQLOpen Source Package PHP & MySQL
Open Source Package PHP & MySQL
 
Object Oriented PHP5
Object Oriented PHP5Object Oriented PHP5
Object Oriented PHP5
 
PHP - Introduction to PHP Functions
PHP -  Introduction to PHP FunctionsPHP -  Introduction to PHP Functions
PHP - Introduction to PHP Functions
 
PHP
PHP PHP
PHP
 
Class 2 - Introduction to PHP
Class 2 - Introduction to PHPClass 2 - Introduction to PHP
Class 2 - Introduction to PHP
 
Codeware
CodewareCodeware
Codeware
 
Twig integration
Twig integrationTwig integration
Twig integration
 
Current state-of-php
Current state-of-phpCurrent state-of-php
Current state-of-php
 
Data Types In PHP
Data Types In PHPData Types In PHP
Data Types In PHP
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
 
Php i basic chapter 3
Php i basic chapter 3Php i basic chapter 3
Php i basic chapter 3
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginning
 
Introduction to PHP Lecture 1
Introduction to PHP Lecture 1Introduction to PHP Lecture 1
Introduction to PHP Lecture 1
 
Basic PHP
Basic PHPBasic PHP
Basic PHP
 
Lca05
Lca05Lca05
Lca05
 
Basics of Java Script (JS)
Basics of Java Script (JS)Basics of Java Script (JS)
Basics of Java Script (JS)
 
Using PHP
Using PHPUsing PHP
Using PHP
 
07 Introduction to PHP #burningkeyboards
07 Introduction to PHP #burningkeyboards07 Introduction to PHP #burningkeyboards
07 Introduction to PHP #burningkeyboards
 

Destaque

Drupal 8: TWIG Template Engine
Drupal 8:  TWIG Template EngineDrupal 8:  TWIG Template Engine
Drupal 8: TWIG Template Enginedrubb
 
Drupal 8 templating with twig
Drupal 8 templating with twigDrupal 8 templating with twig
Drupal 8 templating with twigTaras Omelianenko
 
Drupal 8: Theming
Drupal 8: ThemingDrupal 8: Theming
Drupal 8: Themingdrubb
 
Things Made Easy: One Click CMS Integration with Solr & Drupal
Things Made Easy: One Click CMS Integration with Solr & DrupalThings Made Easy: One Click CMS Integration with Solr & Drupal
Things Made Easy: One Click CMS Integration with Solr & Drupallucenerevolution
 
Single Page Applications in Drupal
Single Page Applications in DrupalSingle Page Applications in Drupal
Single Page Applications in DrupalChris Tankersley
 
Drupal 8: Entities
Drupal 8: EntitiesDrupal 8: Entities
Drupal 8: Entitiesdrubb
 
State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015
State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015
State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015Dropsolid
 
Intro to Apache Solr for Drupal
Intro to Apache Solr for DrupalIntro to Apache Solr for Drupal
Intro to Apache Solr for DrupalChris Caple
 
Building a Custom Theme in Drupal 8
Building a Custom Theme in Drupal 8Building a Custom Theme in Drupal 8
Building a Custom Theme in Drupal 8Anne Tomasevich
 
No pain, no gain. CSS Code Reviews FTW.
No pain, no gain. CSS Code Reviews FTW.No pain, no gain. CSS Code Reviews FTW.
No pain, no gain. CSS Code Reviews FTW.Stacy Kvernmo
 
Drupal 8 + Elasticsearch + Docker
Drupal 8 + Elasticsearch + DockerDrupal 8 + Elasticsearch + Docker
Drupal 8 + Elasticsearch + DockerRoald Umandal
 
Using VueJS in front of Drupal 8
Using VueJS in front of Drupal 8Using VueJS in front of Drupal 8
Using VueJS in front of Drupal 8Brian Ward
 

Destaque (13)

Drupal 8: TWIG Template Engine
Drupal 8:  TWIG Template EngineDrupal 8:  TWIG Template Engine
Drupal 8: TWIG Template Engine
 
Drupal 8 templating with twig
Drupal 8 templating with twigDrupal 8 templating with twig
Drupal 8 templating with twig
 
Drupal 8: Theming
Drupal 8: ThemingDrupal 8: Theming
Drupal 8: Theming
 
Things Made Easy: One Click CMS Integration with Solr & Drupal
Things Made Easy: One Click CMS Integration with Solr & DrupalThings Made Easy: One Click CMS Integration with Solr & Drupal
Things Made Easy: One Click CMS Integration with Solr & Drupal
 
Single Page Applications in Drupal
Single Page Applications in DrupalSingle Page Applications in Drupal
Single Page Applications in Drupal
 
Drupal 8: Entities
Drupal 8: EntitiesDrupal 8: Entities
Drupal 8: Entities
 
State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015
State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015
State of Search, Solr and Facets in Drupal 8 - Drupalcamp Belgium 2015
 
Intro to Apache Solr for Drupal
Intro to Apache Solr for DrupalIntro to Apache Solr for Drupal
Intro to Apache Solr for Drupal
 
Building a Custom Theme in Drupal 8
Building a Custom Theme in Drupal 8Building a Custom Theme in Drupal 8
Building a Custom Theme in Drupal 8
 
No pain, no gain. CSS Code Reviews FTW.
No pain, no gain. CSS Code Reviews FTW.No pain, no gain. CSS Code Reviews FTW.
No pain, no gain. CSS Code Reviews FTW.
 
Drupal 8 + Elasticsearch + Docker
Drupal 8 + Elasticsearch + DockerDrupal 8 + Elasticsearch + Docker
Drupal 8 + Elasticsearch + Docker
 
Using VueJS in front of Drupal 8
Using VueJS in front of Drupal 8Using VueJS in front of Drupal 8
Using VueJS in front of Drupal 8
 
Atomic design
Atomic designAtomic design
Atomic design
 

Semelhante a Making Sense of Twig

Template Toolkit
Template ToolkitTemplate Toolkit
Template Toolkitdwm042
 
Asp.Net MVC - Razor Syntax
Asp.Net MVC - Razor SyntaxAsp.Net MVC - Razor Syntax
Asp.Net MVC - Razor SyntaxRenier Serven
 
Haml & Sass presentation
Haml & Sass presentationHaml & Sass presentation
Haml & Sass presentationbryanbibat
 
Jekyll - Liquid for noobs
Jekyll - Liquid for noobsJekyll - Liquid for noobs
Jekyll - Liquid for noobsBruno Mendes
 
Introduction to Modern Perl
Introduction to Modern PerlIntroduction to Modern Perl
Introduction to Modern PerlDave Cross
 
Component and Event-Driven Architectures in PHP
Component and Event-Driven Architectures in PHPComponent and Event-Driven Architectures in PHP
Component and Event-Driven Architectures in PHPStephan Schmidt
 
My First Rails Plugin - Usertext
My First Rails Plugin - UsertextMy First Rails Plugin - Usertext
My First Rails Plugin - Usertextfrankieroberto
 
DRYing Up Rails Views and Controllers
DRYing Up Rails Views and ControllersDRYing Up Rails Views and Controllers
DRYing Up Rails Views and ControllersJames Gray
 
course slides -- powerpoint
course slides -- powerpointcourse slides -- powerpoint
course slides -- powerpointwebhostingguy
 
Let's write a PDF file
Let's write a PDF fileLet's write a PDF file
Let's write a PDF fileAnge Albertini
 
Building a Rails Interface
Building a Rails InterfaceBuilding a Rails Interface
Building a Rails InterfaceJames Gray
 
Web Development Course: PHP lecture 1
Web Development Course: PHP lecture 1Web Development Course: PHP lecture 1
Web Development Course: PHP lecture 1Gheyath M. Othman
 

Semelhante a Making Sense of Twig (20)

Lettering js
Lettering jsLettering js
Lettering js
 
Php
PhpPhp
Php
 
Template Toolkit
Template ToolkitTemplate Toolkit
Template Toolkit
 
8. radio1 in Symfony 4
8. radio1 in Symfony 48. radio1 in Symfony 4
8. radio1 in Symfony 4
 
Asp.Net MVC - Razor Syntax
Asp.Net MVC - Razor SyntaxAsp.Net MVC - Razor Syntax
Asp.Net MVC - Razor Syntax
 
Haml & Sass presentation
Haml & Sass presentationHaml & Sass presentation
Haml & Sass presentation
 
PHP MySQL
PHP MySQLPHP MySQL
PHP MySQL
 
Jekyll - Liquid for noobs
Jekyll - Liquid for noobsJekyll - Liquid for noobs
Jekyll - Liquid for noobs
 
Introduction to Modern Perl
Introduction to Modern PerlIntroduction to Modern Perl
Introduction to Modern Perl
 
9. lower in Symfony 4
9. lower in Symfony 49. lower in Symfony 4
9. lower in Symfony 4
 
Component and Event-Driven Architectures in PHP
Component and Event-Driven Architectures in PHPComponent and Event-Driven Architectures in PHP
Component and Event-Driven Architectures in PHP
 
My First Rails Plugin - Usertext
My First Rails Plugin - UsertextMy First Rails Plugin - Usertext
My First Rails Plugin - Usertext
 
Php essentials
Php essentialsPhp essentials
Php essentials
 
DRYing Up Rails Views and Controllers
DRYing Up Rails Views and ControllersDRYing Up Rails Views and Controllers
DRYing Up Rails Views and Controllers
 
course slides -- powerpoint
course slides -- powerpointcourse slides -- powerpoint
course slides -- powerpoint
 
Let's write a PDF file
Let's write a PDF fileLet's write a PDF file
Let's write a PDF file
 
Php + my sql
Php + my sqlPhp + my sql
Php + my sql
 
Building a Rails Interface
Building a Rails InterfaceBuilding a Rails Interface
Building a Rails Interface
 
11. move in Symfony 4
11. move in Symfony 411. move in Symfony 4
11. move in Symfony 4
 
Web Development Course: PHP lecture 1
Web Development Course: PHP lecture 1Web Development Course: PHP lecture 1
Web Development Course: PHP lecture 1
 

Último

Deep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampDeep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampVICTOR MAESTRE RAMIREZ
 
How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?AmeliaSmith90
 
Sales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales CoverageSales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales CoverageDista
 
Top Software Development Trends in 2024
Top Software Development Trends in  2024Top Software Development Trends in  2024
Top Software Development Trends in 2024Mind IT Systems
 
Introduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntroduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntelliSource Technologies
 
Kawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in TrivandrumKawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in TrivandrumKawika Technologies
 
JS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AIJS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AIIvo Andreev
 
Why Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfWhy Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfBrain Inventory
 
Webinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptWebinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptkinjal48
 
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsYour Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsJaydeep Chhasatia
 
eAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionseAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionsNirav Modi
 
Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...
Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...
Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...Jaydeep Chhasatia
 
Enterprise Document Management System - Qualityze Inc
Enterprise Document Management System - Qualityze IncEnterprise Document Management System - Qualityze Inc
Enterprise Document Management System - Qualityze Incrobinwilliams8624
 
Fields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxFields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxJoão Esperancinha
 
OpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorOpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorShane Coughlan
 
Cybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and BadCybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and BadIvo Andreev
 
ERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptxERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptxAutus Cyber Tech
 
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdfARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdfTobias Schneck
 
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.Sharon Liu
 
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/MLBig Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/MLAlluxio, Inc.
 

Último (20)

Deep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampDeep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - Datacamp
 
How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?
 
Sales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales CoverageSales Territory Management: A Definitive Guide to Expand Sales Coverage
Sales Territory Management: A Definitive Guide to Expand Sales Coverage
 
Top Software Development Trends in 2024
Top Software Development Trends in  2024Top Software Development Trends in  2024
Top Software Development Trends in 2024
 
Introduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntroduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptx
 
Kawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in TrivandrumKawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in Trivandrum
 
JS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AIJS-Experts - Cybersecurity for Generative AI
JS-Experts - Cybersecurity for Generative AI
 
Why Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfWhy Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdf
 
Webinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptWebinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.ppt
 
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsYour Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
 
eAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionseAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspections
 
Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...
Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...
Optimizing Business Potential: A Guide to Outsourcing Engineering Services in...
 
Enterprise Document Management System - Qualityze Inc
Enterprise Document Management System - Qualityze IncEnterprise Document Management System - Qualityze Inc
Enterprise Document Management System - Qualityze Inc
 
Fields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptxFields in Java and Kotlin and what to expect.pptx
Fields in Java and Kotlin and what to expect.pptx
 
OpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorOpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS Calculator
 
Cybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and BadCybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and Bad
 
ERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptxERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptx
 
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdfARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
 
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
 
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/MLBig Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
 

Making Sense of Twig

  • 3. It’s a templating language. ! All templating features are available globally to all templates in any context, as part of the language. ! It’s not up to each and every application feature to provide its own tags.
  • 4. It’s super powerful. ! - Many ways to stay DRY - Custom variables - Functions - Filters - It knows math - Whitespace control - Extensible
  • 5. Templates get compiled into PHP, so it’s super fast.
  • 6. Twig even makes debugging a piece of cake.
  • 7. Used by some popular apps: ! - LemonStand - Symfony - Craft - others
  • 11. <html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block main %} <p>Hey!</p> {% endblock %} </body> </html>
  • 12. <html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block main %} <p>Hey!</p> {% endblock %} </body> </html>
  • 13. <html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block main %} <p>Hey!</p> {% endblock %} </body> </html>
  • 14. Twig code always lives within one of these three tag pairs: ! {# ... #} {{ ... }} {% ... %}
  • 16. Comment tags are like HTML comments, except they won’t show up in the page source. ! {# This won’t make it to the page source #} ! <!-- This will -->
  • 18. Output tags output stuff to the browser. ! {{ title }} ! {{ "Howdy" }} ! {{ 84 / 2 }}
  • 20. Logic tags (or just “tags”) control the logic of the template: ! - Conditionals - Loops - Variable definitions - Macros - Template includes - etc.
  • 21. The syntax varies from tag to tag.
  • 22. Some are just a single word. ! {% requireLogin %}
  • 24. Some have a closing tag. ! {% block content %} <p>Hey</p> {% endblock %}
  • 25. Some even have nested tags. ! {% if foo %} <p>Something</p> {% else %} <p>Something else</p> {% endif %}
  • 26. It really all depends on the tag. ! The only thing they have in common is that they all start with “{%”, followed by the tag name. ! {% tagname ...
  • 27. Twig comes with several built-in tags. ! {% autoescape %} {% block %} {% filter %} {% do %} {% embed %} {% extends %} {% autoescape %} {% flush %} {% for %} {% from %} {% if %} {% import %} {% include %} {% macro %} {% sandbox %} {% set %} {% spaceless %} {% use %} {% verbatim %}
  • 28. {% autoescape %} ! Escapes text for HTML. ! {% autoescape %} <p>Hey</p> {% endautoescape %} => &lt;p&gt;Hey&lt;/p&gt;
  • 29. {% autoescape %} (Cont.) ! ...or Javascript ! {% autoescape "js" %} http://foo.com {% endautoescape %} => httpx3Ax2Fx2Ffoo.com
  • 30. {% spaceless %} ! Removes any whitespace between Twig/HTML tags. ! {%- spaceless %} <p>Hey there</p> {% endspaceless -%} => <p>Hey there</p>
  • 31. {% verbatim %} ! Defines template code that Twig should output as-is, without parsing. ! {% verbatim %} <p>Type “{{ foo }}”.</p> {% endverbatim %} => <p>Type “{{ foo }}”.</p>
  • 32. You never put a Twig tag inside another Twig tag. ! Bad: ! {{ "Hey {{ firstName }}" }} ! Good: ! {{ "Hey " ~ firstName }}
  • 34. Twig supports five different types of values. ! Strings: "Hey" / 'Hey' Numbers: 42 / 3.14 Booleans: true / false Arrays: ['a', 'b', 'c'] Objects: { foo: 'bar' }
  • 35. An expression is either a solo value, or multiple values combined to form another value. ! "Hey" => "Hey" "Hey "~"there" => "Hey there" 10 => 10 true => true ['a','b','c'] => ['a','b','c'] "Day "~1 => "Day 1" 10*(5+5) => 100
  • 36. Variables are values that get set to a name, to be referenced later. ! Use the {% set %} tag to create them. ! {% set foo = "foo" %} {% set a = 42 %} {% set foobar = foo~"bar" %}
  • 37. The {% set %} tag can also be used as a tag pair. ! {% set foo %} <p>foo</p> {% endset %} ! That’s the same as: ! {% set foo = "n <p>foo</p>n " %}
  • 38. Variables are one tool for keeping our templates DRY. ! {% set title = "About Us" %} ... <title>{{ title }}</title> ... <h1>{{ title }}</h1>
  • 40. Filters modify values. ! They can uppercase text, merge arrays, and lots of other things.
  • 41. To pass a value through a filter, type a pipe (“|”) after the value, followed by the filter name. ! "foo"|upper => "FOO" 21.3|round => 21 ['a','b','c']|length => 3
  • 43. You can even chain them. ! "foobar"|slice(0,3)|upper => FOO
  • 44. You can add filters to variables, too. ! {% set foo = "foo" %} {{ foo|length }} => 3
  • 45. You can use them in pretty much any context you can think of. ! {{ value|filter }} ! {% set foo = value|filter %} ! {% do func(value|filter) %}
  • 46. Filters only modify the value directly before the filter. ! "foo"~"bar"|upper => fooBAR ! ("foo"~"bar")|upper => FOOBAR
  • 47. Twig comes with tons of built-in filters: |abs |batch |capitalize |covert_encoding |date |date_modify |default |escape |first |format |join |json_encode |keys |last |length |lower |nl2br |number_format |merge |upper |raw |replace |reverse |round |slice |sort |split |striptags |title |trim |url_encode
  • 48. |length ! Finds the length of a string or array. ! {{ "foobar"|length }} => 6 ! {{ [1, 2, 3]|length }} => 3
  • 49. |upper & |lower ! Modify the casing of a string. ! {{ "foo"|upper }} => FOO ! {{ "BAR"|lower }} => bar
  • 50. |raw ! Protects a string from getting escaped. ! {{ "<p>Hey</p>" }} => &lt;p&gt;Hey&lt;/&gt; ! {{ "<p>Hey</p>"|raw }} => <p>Hey</p>
  • 51. |date ! Formats a date. ! {{ now|date("F j, Y") }} => April 23, 2014
  • 53. Functions perform functions. ! To call one, type its name, followed by parentheses. ! {{ parent() }}
  • 55. Some of them are global: ! {{ dump(foo) }} ! And they can also be nested within objects: ! {{ craft.isLocalized() }}
  • 56. Twig comes with a few global functions built-in: attribute() block() constant() cycle() date() dump() include() max() min() parent() random() range() source() template_from_string()
  • 57. min() & max() ! Returns the smallest/largest value in a given array. ! {{ min([1, 2, 3]) }} => 1 ! {{ max([1, 2, 3]) }} => 3
  • 58. random() ! {{ random("foobar") }} => f/o/b/a/r ! {{ random([1, 2, 3]) }} => 1/2/3 ! {{ random(10) }} => 1/2/3/4/5/6/7/8/9/10
  • 59. range() ! Creates a range of numbers as an array. ! {% set r = range(1, 5) %} => [1, 2, 3, 4, 5] ! {% set r = [1..5] %} => [1, 2, 3, 4, 5]
  • 60. dump() ! Outputs information about a given variable. Helpful when debugging. ! {{ dump(foo) }} ! (In Craft, dump() is only available in Dev Mode.)
  • 62. You can prevent certain parts of your template from executing unless a certain condition is met by wrapping it in conditional tags.
  • 63. Conditionals always open with an {% if %} tag, and close with an {% endif %} tag. ! {% if user %} <p>Hey there handsome!</p> {% endif %}
  • 64. You can also specify template code to be executed if the condition doesn’t pass, using the {% else %} tag. ! {% if user %} <p>Hey there handsome!</p> {% else %} <p>Have we met?</p> {% endif %}
  • 65. There’s also an {% elseif %} tag if you need fallback conditions. ! {% if user %} <p>Hey there handsome!</p> {% elseif username %} <p>Is this {{ username }}?</p> {% else %} <p>Have we met?</p> {% endif %}
  • 66. Conditionals can be nested. ! {% if user %} {% if user.male %} <p>Hey there handsome!</p> {% else %} <p>Hey pretty lady!</p> {% endif %} {% elseif username %} <p>Is this {{ username }}?</p> {% else %} <p>Have we met?</p> {% endif %}
  • 67. A single condition can be made up of multiple expressions joined together with “and” or “or”. ! {% if foo and bar %} ! {% if foo or bar %}
  • 68. You can negate a condition by typing “not” before it. ! {% if not foo %}
  • 69. You can also group expressions together using parentheses. ! {% if foo and ( foo == "foo" or foo == "bar" ) %}
  • 70. Tests
  • 71. Tests are little conditional helpers. They don’t have to be used within conditionals, but usually are.
  • 72. To write a test, add either “is” or “is not” after a variable, followed by the test name. ! {% if foo is defined %} ! {% if foo is not empty %}
  • 73. Twig comes with a few tests built-in. ! is constant is defined is divisible by is empty is even is iterable is null is odd is same as
  • 74. is defined ! Tests whether a variable exists at all, without Twig getting mad at you if it’s not. ! {% if foo is defined %}
  • 75. is divisible by ! Tests whether a number is divisible by another. ! {% if 5 is divisible by(2) %} ! That’s similar to writing: ! {% if 5 % 2 == 0 %}
  • 76. is even & is odd ! Tests whether a number is even/odd. ! {% if 5 is even %} ! {% if 5 is odd %}
  • 77. is empty ! Tests whether a variable is “empty”. ! {% if foo is not empty %} ! That’s the same as writing: ! {% if foo %}
  • 78. is same as ! Tests whether two variables have the same *type*. ! {% if 5 == "5" %} => true ! {% if 5 is same as "5" %} => false
  • 80. Arrays and objects both contain multiple values.
  • 81. Arrays contain values in a specific order, and have an inherent numerical index. ! {% set arr = ['a','b','c'] %} ! {{ arr[0] }} => 'a' {{ arr[1] }} => 'b' {{ arr[2] }} => 'c'
  • 82. Objects contain key-value pairs, and the order is generally less important. ! {% set obj = { foo: "Foo", bar: "Bar" } %} ! {{ obj.foo }} => "Foo" {{ obj.bar }} => "Bar"
  • 83. You can merge arrays together with the ‘merge’ filter. ! {% set a1 = ['a','b'] %} {% set a2 = ['c','d'] %} {% set a3 = a1|merge(a2) %} ! => ['a','b','c','d']
  • 84. You can merge objects together too. ! {% set o1 = {foo: "Foo"} %} {% set o2 = {bar: "Bar"} %} {% set o3 = o1|merge(o2) %} ! => {foo: "Foo", bar: "Bar"}
  • 85. You can grab part of an array with the “slice” filter. ! {% set a1 = ['a','b','c'] %} {% set a2 = a1|slice(0, 2) %} ! => ['a','b'] ! A shortcut is also available: ! {% set a2 = a1[0:2] %}
  • 87. You can loop through arrays with the {% for %} tag. ! The syntax is: ! {% for itemname in myarray %} ... {% endfor %} ! The 2nd param (“itemname”) is whatever you want to call each item within the array.
  • 88. Example 1: Age field ! <select name="age"> {% for age in [0..150] %} <option> {{ age }}</option> {% endfor %} </select>
  • 89. Example 2: Exp. Year field ! {% set y1 = now.year %} {% set y2 = y1 + 10 %} ! <select name="exp_year"> {% for year in [y1..y2] %} <option> {{ year }}</option> {% endfor %} </select>
  • 90. Example 3: Navigation ! {% set nav = [ { title: "Home", uri: "" }, { title: "About", uri: "about" } ] %} ! <nav> {% for item in nav %} <a href="{{ url(item.uri) }}"> {{ item.title }}</a> {% endfor %} </nav>
  • 93. Templates can include others. Include Template Parent Template Parent Template
  • 94. Use the {% include %} tag to include another template wherever the tag is placed. ! {% include "some/template" %}
  • 95. By default, any variables available to the “parent” template will also be available in the included template. ! {% set foo = "foo" %} {% include "myinclude" %} ! myinclude.html: {{ foo }} => foo
  • 96. You can define additional variables just for the included template using the “with” param. ! {% include "myinclude" with { foo: "foo" } %} ! some/template.html: {{ foo }} => foo
  • 97. To *only* pass certain variables to the included template, use the “only” param. ! {% set foo = "foo" %} {% include "myinclude" with { bar: "bar" } only %} ! some/template.html: {% if foo is defined %} => false
  • 99. A template can extend another, overriding parts of it (called “blocks”). Parent Template Block Child Template Child Template
  • 100. Define overridable areas in the parent template using the {% block %} tag. ! <body> {% block body %} <p>Default content</p> {% endblock %} </body>
  • 101. Use the {% extends %} tag within your child template to tell it which template it extends. ! {% extends "layout" %}
  • 102. Override the parent’s blocks by creating new blocks in the child template with the same name. ! {% extends "layout" %} ! {% block body %} <p>Override content</p> {% endblock %}
  • 103. You can output the parent block’s content using the parent() function. ! {% extends "layout" %} ! {% block body %} {{ parent() }} <p>Additional content</p> {% endblock %}
  • 106. Twig also lets you “embed” other templates, which is similar to including them, except you get to override the child template’s blocks in the process.
  • 108. Use the {% embed %} tag to embed another template. ! {% embed "promo" %} {% block body %} {{ parent() }} <span class="ribbon"> 50% off! </span> {% endblock %} {% endembed %}
  • 109. Macros
  • 110. Macros are like includes that are defined right within another template.
  • 111. Use the {% macro %} tag to define them. ! {% macro errors(list) %} {% if list|length %} <ul class="errors"> {% for error in list %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} {% endmacro %}
  • 112. You must import macros before you can use them, with either {% from %} or {% import %}. ! {% from _self import errors %} {{ errors(entry.allErrors) }} ! ! {% import _self as m %} {{ m.errors(entry.allErrors) }}
  • 113. You can import macros from other templates, too. ! {% from "macros" import errors %} {{ errors(entry.allErrors) }} ! ! {% import "macros" as m %} {{ m.errors(entry.allErrors) }} !