Twig internals
About speaker
What is Twig?
Maintenance page of Bartik theme.
Drupal 7, PHP templateDrupal 8, Twig template
Why we are here?
To remember (or learn) the basics of Twig
Recall Twig main features and advantages
Find out extending possibilities
Debug Twig core a little bit
Print data
{{ foo }}
Twig start points
Do something
{% for %}
Basic syntax
strings
numbers
objects
arrays
null
true
false
hashes
{% for value in Traversable %}
{% else %}
{% endfor %}
{% if expression %}
{% elseif %}
{% endif %}
{% else %}
-> .
~.
Data types OperatorsControl
Structures
Functions
Tests
Filters
From Functions to Filters and Tests
Functions in Twig works the same as in PHP – they apply arguments in parentheses and return result.
Filters are modifying the value by some
rules.
Value Filter Params
Tests are checking the value by test
rule.
Value Test Paramsis
Test sign
Filter sign
Extending templatesLayout
block header
block footer
Bloc
k si
deba
r
block content
Module template
Bloc
k si
deba
r
extends
Your template
block content
Block definitions in child templates replace its content in parent template
You have to define only that blocks that you want to overwrite
You can overwrite any block from parent template
extends
Replaces per block
Re-usage of templates
Your template
Parent template
Layout
Parent template
{% extends … %}
Replaces per block
Block definitions
{% use … %}
Peace of template
{% include … %}
Macro(Peace of template
with arguments)
{% import … %}
{% embed … %}
Creating Twig extensionclass MyExtension extends Twig_Extension{
public function getFilters(){
return array(new Twig_SimpleFilter(‘my_filter', ‘callback'),
);}
}
$twig->addExtension(new MyExtension());
Custom extension allows to define:
• Globals
• Functions
• Filters
• Tags
• Tests
• Operators
Extending Twig for Jedi
Make a service
global for twig
Create a macro when need to
reuse template with parameters
Forgot to calculate some stuff before rendering template? - Go to the dark side, make your service global
Want to define some logic in declarative way? - Do not restrain your emotions, make a macro
For strong minds the only way is to write custom tag, in custom bundle and publish it on GitHubTwig
Extension
Also you could create a Twig extension to define your functions, filters, tests and operators. And share the extension between projects
Custom tag
How it works?
Data from controller
Lexer
Parser
Compiler
Caching system
Web page
Hello word!index.html.twi
g Evaluate
Lexer splits input text into language
primitives in one stream
Parser builds node tree according to nesting rules
(Abstract Syntax Tree)
Compiler generates PHP code based on Abstract syntax Tree
Each template is represented as a PHP class in the caching
system
First time Twig has to parse input file and build cache entry
Lexer
1 Hello.2 {{.name|capitalize.}}3
For example there is a file index.html.twigLexer understands language primitives and outputs them in one stream
Lexer
Hm.. There is some text.TEXT_TYPE(“Hello \n”)
Hm.. Seems this is start of tagVAR_START_TYPE()
TEXT_TYPE(“Hello \n”),
VAR_START_TYPE(),
NAME_TYPE(“name”),
OPERATOR_TYPE(“|”),
NAME_TYPE(“capitalize”),
VAR_END_TYPE(),
EOF_TYPE()
Now I see a variableNAME_TYPE(“name”)
Hm.. Some operatorOPERATOR_TYPE(“|”)
Wow! Again some nameNAME_TYPE(“capitalize”)
Parser
Parser
TEXT_TYPE(“Hello \n”),
VAR_START_TYPE(),
NAME_TYPE(“name”),
OPERATOR_TYPE(“|”),
NAME_TYPE(“capitalize”),
VAR_END_TYPE(),
EOF_TYPE()
Template: index.html.twig
Text: “Hello \n”
Echo result of calculation
Filter: capitalize
Value of variable “name”
The goal of parser is to find dependencies between elements. It understands that one thing can contain others. At the end if builds the whole document in object-oriented way when one objects consist of other.
CompilerTemplate: index.html.twig
Text: “Hello \n”
Echo result of calculation
Filter: capitalize
Value of variable “name”
Compiler is a tool that converts Abstract Syntax Tree into a PHP code. For each type of node compiler has own handlers. Each handler knows how to transform node of AST into raw PHP string. So, at the output we have PHP code in one stream.
Compiler
echo “Hello \n”;echo ucfirst($name);
This code will be put into PHP representation
of index.html.twig
The power of customization
Lexer
Goals Solutions
As a PHP lover I want to support <?: ?> tagsso that it makes me happy
As an idealist I need {% single %} case in “for” tagSo that it controls case when there is only one element in input data
As a “hot fixer”I want to have {% log %} tagso that I can save data between tags into log file
Parser
Compiler
Create a node class that implements Twig_NodeInterface. Define custom logic in compile() method. You also need to create custom TokenParser to initialize new node class.
Create a Token Parser class that implements Twig_TokenParserInterface. Define you logic in parse() method. Use existing compilers for all cases.
Change default Twig lexer with custom one that extends from core and understands new tags as {{ and }}
Sandbox – include untrusted templates
Secure template include
Users can edit templates online ?
They can do something you wouldn’t like
Let’s filter user’s input by white-list rules!
In sandboxed template you can use only allowed:
• Methods of your classes,
• Properties of your classes
• Filters
• Tags
Find your reason to love Twig Twig is a modern template engine for PHP
Fast: Twig compiles templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum.
Secure: Twig has a sandbox mode to evaluate untrusted template code. This allows Twig to be used as a template language for applications where users may modify the template design.
Flexible: Twig is powered by a flexible lexer and parser. This allows the developer to define its own custom tags and filters, and create its own DSL.
Top Related