0
TWIG
The flexible, fast, and secure template
language for PHP
Cesare D'Amico
cesare@wyrd.it
Cesare D'Amico
freelance php dev
Hi, nice to meet you!
cesare@wyrd.it
Twitter: __ce (double underscore)
http://cesaredami....
A bit of history
“So, you think PHP is a templating engine?”
Fabien Potencier - October 07, 2009
http://j.mp/lOnJU
In his ...
A bit of history
Available solutions (October 2009):
●
Smarty3: slow
●
PHPTAL: HTML only
●
ez Components: slowest, no
inhe...
TWIG
●
Fast: Twig compiles templates to plain
optimized PHP code
●
Secure: sandbox mode for untrusted
template code
●
Flex...
Assignments
{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = ['foo': 'bar'] %}
{% set foo = 'foo' ~ 'bar' %}
{% s...
Control structures – for
{% for user in users %}
{% for i in 0..10 %}
{% for l in 'a'..'z' %}
{% for l in 'a'|upper..'z'|u...
Control structures – for
loop.index
loop.index0
loop.revindex *
loop.revindex0 *
loop.first (boolean)
loop.last *  (boolea...
Control structures – for
<ul>
  {% for user in users %}
    <li>{{ user.username|e }}</li>
  {% else %}
    <li><em>no use...
Control structures – for
<ul>
  {% for id in users|keys %}
    <li>{{ id }}</li>
  {% endfor %}
</ul>
Control structures – for
<ul>
  {% for id, user in users %}
    <li>{{ id }}: {{ user.username|e }}</li>
  {% endfor %}
</...
Control structures – if
{% if users %}
  <ul>
    {% for user in users %}
      <li>{{ user.username|e }}</li>
    {% endf...
Control structures – if/else
{% if kenny.sick %}
  Kenny is sick.
{% elseif kenny.dead %}
  You killed Kenny! You bastard!...
Expressions: literals & math
"Hello World"
42 / 42.23
[foo, bar]
true / false
none
+ ­ * / %
//
**
Expressions: logic &
comparison
and or not (expression)
< > <= >= == !=
range comparisons:
{% if 1 < a < 4 %}
Even more operators!
in
.. (range)
| (apply filter)
~ (string concatenation)
. [] (attribute access: a­la object/array)
?:...
Filters: built-in
date: {{ post.published_at|date("m/d/Y") }}
format: “I like %s and %s”
{{ string|format(foo, "bar") }}
r...
Tests: built-in
divisibleby: {% if loop.index is divisibleby(3) %}
none: {{ var is none }}
even, odd
Everyone still awake?
(the best is coming...)
Inheritance – base file
<html>
<head>
{% block head %}
  <link rel="stylesheet" href="style.css" />
  <title>{% block titl...
Inheritance – base file
<body>
  <div id="content">
    {% block content %}{% endblock %}
  </div>
  <div id="footer">
   ...
Inheritance – child template
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
  {% parent %...
Inheritance – child template
{% block content %}
  <h1>Index</h1>
  <p class="important">
    Welcome on my awesome homepa...
Dynamic & conditional
inheritance
{% extends some_var %}
{% extends ajax_output ? "ajax.html"
                       : "la...
include
{% include 'header.html' %}
...Body...
{% include 'footer.html' %}
{% include 'foo' with ['foo': 'bar'] %}
{% set ...
Macros
{% macro input(name, value, type, size) %}
  <input type="{{ type|default('text') }}"
     name="{{ name }}" value=...
Macros – calling
<p>{{ _self.input('username') }}</p>
<p>{{ _self.textarea(
         'description',
         '...',
      ...
import
{% import 'forms.html' as forms %}
<dl>
  <dt>Username</dt>
  <dd>{{ forms.input('username') }}</dd>
  <dt>Password...
import – hang yourself...
{% macro input(name, value, type, size) %}
  <input type="{{ type|default('text') }}"
     name=...
i18n – needs gettext!
{% trans "Hello World!" %}
 
{% trans string_var %}
{% trans %}Hello World!{% endtrans %}
{% trans %...
i18n – plurals
{% trans %}
    Hey {{ name }}, I have one apple.
{% plural apple_count %}
    Hey {{ name }}, I have {{ co...
Let's use it: environment
<?php
require_once 
'/path/to/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
 
$loader =...
Let's use it: render
<?php
$template = $twig­>loadTemplate('tpl.html');
echo $template­>render(array(
  'the' => 'variable...
Built-in loaders
$l = new Twig_Loader_Filesystem($tplDir);
$l = new Twig_Loader_Filesystem(
  array($tplDir1, $tplDir2)
);...
Built-in extensions
Core (automatically registered)
Escaper
Sandbox
I18n
You can create your own extensions if you need so...
Thanks everyone!
?
12-14 Maggio 2011
http://www.phpday.it/
Please, rate this talk!
Feel like bashing?
Urge saying you fell in love
with this presentation?
Now you can!
http://joind....
Upcoming SlideShare
Loading in...5
×

TWIG: the flexible, fast and secure template language for PHP

6,299

Published on

TWIG is a template engine created by Fabien Potencier, the father of Symfony. In this talk you'll learn why he wrote it, its main features and strengths.

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,299
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
47
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "TWIG: the flexible, fast and secure template language for PHP"

  1. 1. TWIG The flexible, fast, and secure template language for PHP Cesare D'Amico cesare@wyrd.it
  2. 2. Cesare D'Amico freelance php dev Hi, nice to meet you! cesare@wyrd.it Twitter: __ce (double underscore) http://cesaredami.co/
  3. 3. A bit of history “So, you think PHP is a templating engine?” Fabien Potencier - October 07, 2009 http://j.mp/lOnJU In his opinion, php lacks: ● concision (<?php echo $var ?>) ● template-oriented syntax (foreach()) ● reusability ● security + sandbox mode
  4. 4. A bit of history Available solutions (October 2009): ● Smarty3: slow ● PHPTAL: HTML only ● ez Components: slowest, no inheritance ● Dwoo: no inheritance ● Calypso: broken (in his author's words)
  5. 5. TWIG ● Fast: Twig compiles templates to plain optimized PHP code ● Secure: sandbox mode for untrusted template code ● Flexible: powered by a flexible lexer and parser, this allows to define custom tags and filters
  6. 6. Assignments {% set foo = 'foo' %} {% set foo = [1, 2] %} {% set foo = ['foo': 'bar'] %} {% set foo = 'foo' ~ 'bar' %} {% set foo, bar = 'foo', 'bar' %} {% set foo %}   <div id="pagination">     ...   </div> {% endset %}
  7. 7. Control structures – for {% for user in users %} {% for i in 0..10 %} {% for l in 'a'..'z' %} {% for l in 'a'|upper..'z'|upper %} {% for i in 0|range(10, 2) %}
  8. 8. Control structures – for loop.index loop.index0 loop.revindex * loop.revindex0 * loop.first (boolean) loop.last *  (boolean) loop.length * loop.parent * Only for arrays and objects implementing the Countable interface
  9. 9. Control structures – for <ul>   {% for user in users %}     <li>{{ user.username|e }}</li>   {% else %}     <li><em>no user found</em></li>   {% endfor %} </ul>
  10. 10. Control structures – for <ul>   {% for id in users|keys %}     <li>{{ id }}</li>   {% endfor %} </ul>
  11. 11. Control structures – for <ul>   {% for id, user in users %}     <li>{{ id }}: {{ user.username|e }}</li>   {% endfor %} </ul>
  12. 12. Control structures – if {% if users %}   <ul>     {% for user in users %}       <li>{{ user.username|e }}</li>     {% endfor %}   </ul> {% endif %}
  13. 13. Control structures – if/else {% if kenny.sick %}   Kenny is sick. {% elseif kenny.dead %}   You killed Kenny! You bastard!!! {% else %}   Kenny looks okay ­­­ so far {% endif %}
  14. 14. Expressions: literals & math "Hello World" 42 / 42.23 [foo, bar] true / false none + ­ * / % // **
  15. 15. Expressions: logic & comparison and or not (expression) < > <= >= == != range comparisons: {% if 1 < a < 4 %}
  16. 16. Even more operators! in .. (range) | (apply filter) ~ (string concatenation) . [] (attribute access: a­la object/array) ?: (ternary operator)
  17. 17. Filters: built-in date: {{ post.published_at|date("m/d/Y") }} format: “I like %s and %s” {{ string|format(foo, "bar") }} replace: “I like %this% and %that%” {{ string|format(['%this%': foo, '%that%': "bar"]) }} url_encode, json_encode, title, capitalize, upper, lower, striptags, join, reverse, length, sort, default, keys, escape / e, raw
  18. 18. Tests: built-in divisibleby: {% if loop.index is divisibleby(3) %} none: {{ var is none }} even, odd
  19. 19. Everyone still awake? (the best is coming...)
  20. 20. Inheritance – base file <html> <head> {% block head %}   <link rel="stylesheet" href="style.css" />   <title>{% block title %}{% endblock  %}</title> {% endblock %} </head>
  21. 21. Inheritance – base file <body>   <div id="content">     {% block content %}{% endblock %}   </div>   <div id="footer">     {% block footer %}     &copy; Copyright 2010 by you.     {% endblock %}   </div> </body> </html>
  22. 22. Inheritance – child template {% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %}   {% parent %}   <style type="text/css">     .important { color: #336699; }   </style> {% endblock %}
  23. 23. Inheritance – child template {% block content %}   <h1>Index</h1>   <p class="important">     Welcome on my awesome homepage.   </p> {% endblock %}
  24. 24. Dynamic & conditional inheritance {% extends some_var %} {% extends ajax_output ? "ajax.html"                        : "layout.html" %}
  25. 25. include {% include 'header.html' %} ...Body... {% include 'footer.html' %} {% include 'foo' with ['foo': 'bar'] %} {% set vars = ['foo': 'bar'] %} {% include 'foo' with vars %} {% include some_var %} {% include ajax ? 'ajax.html':'base.html' %}
  26. 26. Macros {% macro input(name, value, type, size) %}   <input type="{{ type|default('text') }}"      name="{{ name }}" value="{{ value|e }}"      size="{{ size|default(20) }}" /> {% endmacro %} {% macro textarea(name, value, rows) %}   <textarea name="{{ name }}"       rows="{{ rows|default(10) }}"      cols="{{ cols|default(40) }}">      {{ value|e }}   </textarea> {% endmacro %}
  27. 27. Macros – calling <p>{{ _self.input('username') }}</p> <p>{{ _self.textarea(          'description',          '...',          8       ) }}</p>
  28. 28. import {% import 'forms.html' as forms %} <dl>   <dt>Username</dt>   <dd>{{ forms.input('username') }}</dd>   <dt>Password</dt>   <dd>{{ forms.input('password', none,  'password') }}</dd> </dl> <p>{{ forms.textarea('comment') }}</p>
  29. 29. import – hang yourself... {% macro input(name, value, type, size) %}   <input type="{{ type|default('text') }}"      name="{{ name }}" value="{{ value|e }}"      size="{{ size|default(20) }}" /> {% endmacro %} {% import _self as forms %}   <p>{{ forms.input('text','username') }}</p>
  30. 30. i18n – needs gettext! {% trans "Hello World!" %}   {% trans string_var %} {% trans %}Hello World!{% endtrans %} {% trans %}Hello {{ name }}!{% endtrans %} {% trans Hello {{ name }}! %}
  31. 31. i18n – plurals {% trans %}     Hey {{ name }}, I have one apple. {% plural apple_count %}     Hey {{ name }}, I have {{ count }}  apples. {% endtrans %}
  32. 32. Let's use it: environment <?php require_once  '/path/to/lib/Twig/Autoloader.php'; Twig_Autoloader::register();   $loader = new  Twig_Loader_Filesystem('/path/to/templates'); $twig = new Twig_Environment($loader, array(   'cache' => '/path/to/compilation_cache', ));
  33. 33. Let's use it: render <?php $template = $twig­>loadTemplate('tpl.html'); echo $template­>render(array(   'the' => 'variables',    'go' => 'here' )); Same as: $template­>display(...)
  34. 34. Built-in loaders $l = new Twig_Loader_Filesystem($tplDir); $l = new Twig_Loader_Filesystem(   array($tplDir1, $tplDir2) ); Dummy: $loader = new Twig_Loader_String("..."); For unit testing: $loader = new Twig_Loader_Array($templates);
  35. 35. Built-in extensions Core (automatically registered) Escaper Sandbox I18n You can create your own extensions if you need so: - implement interface Twig_ExtensionInterface - extend Twig_Extension so you need only implement needed methods $twig­>addExtension(   new Twig_Extension_Escaper() );
  36. 36. Thanks everyone! ?
  37. 37. 12-14 Maggio 2011 http://www.phpday.it/
  38. 38. Please, rate this talk! Feel like bashing? Urge saying you fell in love with this presentation? Now you can! http://joind.in/2151
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×