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

Embed Size (px)

Citation preview

Folie 1

TWIG

The flexible, fast, and secure template language for PHP

Cesare D'[email protected]

Cesare D'Amicofreelance php dev

Hi, nice to meet you!

[email protected]: __ce (double underscore)http://cesaredami.co/

A bit of history

So, you think PHP is a templating engine?Fabien Potencier - October 07, 2009http://j.mp/lOnJU

In his opinion, php lacks:

concision ()

template-oriented syntax (foreach())

reusability

security + sandbox mode

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)

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

Assignments

{% set foo = 'foo' %}{% set foo = [1, 2] %}{% set foo = ['foo': 'bar'] %}{% set foo = 'foo' ~ 'bar' %}{% set foo, bar = 'foo', 'bar' %}

{% set foo %} ... {% endset %}

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) %}

Control structures for

loop.indexloop.index0loop.revindex *loop.revindex0 *loop.first (boolean)loop.last * (boolean)loop.length *loop.parent

* Only for arrays and objects implementing the Countable interface

Control structures for

  • {% for user in users %}
  • {{ user.username|e }} {% else %}
  • no user found {% endfor %}

Control structures for

  • {% for id in users|keys %}
  • {{ id }} {% endfor %}

Control structures for

  • {% for id, user in users %}
  • {{ id }}: {{ user.username|e }} {% endfor %}

Control structures if

{% if users %}

  • {% for user in users %}
  • {{ user.username|e }} {% endfor %}

{% endif %}

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 %}

Expressions: literals & math

"Hello World"42 / 42.23[foo, bar]true / falsenone

+ - * / %//**

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)?: (ternary operator)

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

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

{% block head %} {% block title %}{% endblock %}{% endblock %}

Inheritance base file

{% block content %}{% endblock %} {% block footer %} Copyright 2010 by you. {% endblock %}

Inheritance child template

{% extends "base.html" %}{% block title %}Index{% endblock %}{% block head %} {% parent %} .important { color: #336699; } {% endblock %}

Inheritance child template

{% block content %} Index Welcome on my awesome homepage. {% endblock %}

Dynamic & conditional inheritance

{% extends some_var %}

{% extends ajax_output ? "ajax.html" : "layout.html" %}

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' %}

Macros

{% macro input(name, value, type, size) %} {% endmacro %}{% macro textarea(name, value, rows) %} {{ value|e }} {% endmacro %}

Macros calling

{{ _self.input('username') }}

{{ _self.textarea( 'description', '...', 8 ) }}

import

{% import 'forms.html' as forms %}

Username {{ forms.input('username') }} Password {{ forms.input('password', none, 'password') }}

{{ forms.textarea('comment') }}

import hang yourself...

{% macro input(name, value, type, size) %} {% endmacro %}

{% import _self as forms %} {{ forms.input('text','username') }}

i18n needs gettext!

{% trans "Hello World!" %} {% trans string_var %}

{% trans %}Hello World!{% endtrans %}

{% trans %}Hello {{ name }}!{% endtrans %}{% trans Hello {{ name }}! %}

i18n plurals

{% trans %} Hey {{ name }}, I have one apple.{% plural apple_count %} Hey {{ name }}, I have {{ count }} apples.{% endtrans %}

Let's use it: environment