• Like

Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

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

  • 6,033 views
Uploaded 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.

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.

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,033
On Slideshare
0
From Embeds
0
Number of Embeds
3

Actions

Shares
Downloads
44
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1.
      TWIG
      The flexible, fast, and secure template language for PHP
      Cesare D'Amico
    • [email_address]
  • 2. Cesare D'Amico freelance php dev
      Hi, nice to meet you!
    [email_address] Twitter: __ce (double underscore) http://cesaredami.co/
  • 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())
    • 4. reusability
    • 5. security + sandbox mode
  • 6. A bit of history Available solutions (October 2009):
    • Smarty3: slow
    • PHPTAL: HTML only
    • 7. ez Components: slowest, no inheritance
    • 8. Dwoo: no inheritance
    • 9. Calypso: broken (in his author's words)
  • 10. TWIG
    • Fast: Twig compiles templates to plain optimized PHP code
    • 11. Secure: sandbox mode for untrusted template code
    • 12. Flexible: powered by a flexible lexer and parser, this allows to define custom tags and filters
  • 13. 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=&quot;pagination&quot;> ... </div> {% endset %}
  • 14. 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) %}
  • 15. 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
  • 16. Control structures – for <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% else %} <li><em>no user found</em></li> {% endfor %} </ul>
  • 17. Control structures – for <ul> {% for id in users|keys %} <li>{{ id }}</li> {% endfor %} </ul>
  • 18. Control structures – for <ul> {% for id, user in users %} <li>{{ id }}: {{ user.username|e }}</li> {% endfor %} </ul>
  • 19. Control structures – if {% if users %} <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul> {% endif %}
  • 20. 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 %}
  • 21. Expressions: literals & math &quot;Hello World&quot; 42 / 42.23 [foo, bar] true / false none + - * / % // **
  • 22. Expressions: logic & comparison and or not (expression) < > <= >= == != range comparisons: {% if 1 < a < 4 %}
  • 23. Even more operators! in .. (range) | (apply filter) ~ (string concatenation) . [] (attribute access: a-la object/array) ?: (ternary operator)
  • 24. Filters: built-in date: {{ post.published_at|date(&quot;m/d/Y&quot;) }} format: “I like %s and %s” {{ string|format(foo, &quot;bar&quot;) }} replace: “I like %this% and %that%” {{ string|format(['%this%': foo, '%that%': &quot;bar&quot;]) }} url_encode, json_encode, title, capitalize, upper, lower, striptags, join, reverse, length, sort, default, keys, escape / e, raw
  • 25. Tests: built-in divisibleby: {% if loop.index is divisibleby(3) %} none: {{ var is none }} even, odd
  • 26. Everyone still awake? (the best is coming...)
  • 27. Inheritance – base file <html> <head> {% block head %} <link rel=&quot;stylesheet&quot; href=&quot;style.css&quot; /> <title>{% block title %}{% endblock %}</title> {% endblock %} </head>
  • 28. Inheritance – base file <body> <div id=&quot;content&quot;> {% block content %}{% endblock %} </div> <div id=&quot;footer&quot;> {% block footer %} &copy; Copyright 2010 by you. {% endblock %} </div> </body> </html>
  • 29. Inheritance – child template {% extends &quot;base.html&quot; %} {% block title %}Index{% endblock %} {% block head %} {% parent %} <style type=&quot;text/css&quot;> .important { color: #336699; } </style> {% endblock %}
  • 30. Inheritance – child template {% block content %} <h1>Index</h1> <p class=&quot;important&quot;> Welcome on my awesome homepage. </p> {% endblock %}
  • 31. Dynamic & conditional inheritance {% extends some_var %} {% extends ajax_output ? &quot;ajax.html&quot; : &quot;layout.html&quot; %}
  • 32. 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' %}
  • 33. Macros {% macro input(name, value, type, size) %} <input type=&quot;{{ type|default('text') }}&quot; name=&quot;{{ name }}&quot; value=&quot;{{ value|e }}&quot; size=&quot;{{ size|default(20) }}&quot; /> {% endmacro %} {% macro textarea(name, value, rows) %} <textarea name=&quot;{{ name }}&quot; rows=&quot;{{ rows|default(10) }}&quot; cols=&quot;{{ cols|default(40) }}&quot;> {{ value|e }} </textarea> {% endmacro %}
  • 34. Macros – calling <p>{{ _self.input('username') }}</p> <p>{{ _self.textarea( 'description', '...', 8 ) }}</p>
  • 35. 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>
  • 36. import – hang yourself... {% macro input(name, value, type, size) %} <input type=&quot;{{ type|default('text') }}&quot; name=&quot;{{ name }}&quot; value=&quot;{{ value|e }}&quot; size=&quot;{{ size|default(20) }}&quot; /> {% endmacro %} {% import _self as forms %} <p>{{ forms.input('text','username') }}</p>
  • 37. i18n – needs gettext! {% trans &quot;Hello World!&quot; %} {% trans string_var %} {% trans %}Hello World!{% endtrans %} {% trans %}Hello {{ name }}!{% endtrans %} {% trans Hello {{ name }}! %}
  • 38. i18n – plurals {% trans %} Hey {{ name }}, I have one apple. {% plural apple_count %} Hey {{ name }}, I have {{ count }} apples. {% endtrans %}
  • 39. 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', ));
  • 40. Let's use it: render <?php $template = $twig->loadTemplate('tpl.html'); echo $template->render(array( 'the' => 'variables', 'go' => 'here' )); Same as: $template->display(...)
  • 41. Built-in loaders $l = new Twig_Loader_Filesystem($tplDir); $l = new Twig_Loader_Filesystem( array($tplDir1, $tplDir2) ); Dummy: $loader = new Twig_Loader_String(&quot;...&quot;); For unit testing: $loader = new Twig_Loader_Array($templates);
  • 42. 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() );
  • 43. Thanks everyone! ?
  • 44.
      12-14 Maggio 2011
    • http://www.phpday.it/
  • 45. Please, rate this talk! Feel like bashing? Urge saying you fell in love with this presentation? Now you can! http://joind.in/2151