SlideShare a Scribd company logo
1 of 45
Download to read offline
Twig
The flexible, fast, and secure
template language for PHP

Fabien Potencier
Fabien Potencier
•  Serial entrepreneur and developer by passion
•  Founder of Sensio
   –  Web Agency (France and USA)
   –  Since 1998
   –  70 people
   –  Open-Source Specialists
   –  Big corporate customers
   –  Consulting, training, development, web design, … and more

   –  Sponsor of a lot of Open-Source projects
      like symfony and Doctrine
Fabien Potencier
•  Creator and lead developer of symfony…
•  and creator and lead developer of some more:
   –  symfony components
   –  Swift Mailer : Powerful component based mailing library for PHP
   –  Twig : Fexible, fast, and secure template language for PHP
   –  Pirum : Simple PEAR Channel Server Manager
   –  Sismo : PHP continuous integration server
   –  Lime : Easy to use unit testing library for PHP
   –  Twitto : A web framework in a tweet
   –  Twittee : A Dependency Injection Container in a tweet
   –  Pimple : A small PHP 5.3 dependency injection container
Fabien Potencier

•  Read my technical blog: http://fabien.potencier.org/

•  Follow me on Twitter: @fabpot

•  Fork my code on Github: http://github.com/fabpot/
http://www.twig-project.org/
Twig history


I was looking for a good template engine

I don’t like to reinvent the wheel

I started to look around for existing ones
Twig history
But I found none that satisfied all my personal needs:
   –  Fast (templates should be compiled to PHP)
   –  Secure (flexible output escaping)
   –  Sandboxed (whitelist system)
   –  Not tied to only HTML templates (emails, …)
   –  Syntax similar to Django & Jinja (but flexible, nothing hardcoded)
   –  Embeddable
   –  “Modern” features (such as template inheritance)
   –  Easily extensible (should be able to override everything)
   –  Clean OO code (“real” lexer, parser, and compiler, DI)
Twig history
•  … except Twig, which was quite close and had a solid architecture

   –  written by Armin Ronacher (of Jinja fame – a python template engine)

•  … but

   –  not available as a standalone project (packaged with chypr, a blog platform)

   –  never really maintained

•  I stumbled upon it by chance
Twig history
•  I started hacking the code, found it immediately beautiful and flexible
•  I wrote an email to Armin
•  and I took over the maintenance of it
   –  I’m the lead developer since October 1st
   –  kept the source under a BSD license
   –  created a dedicated website, mailing-list, wrote some documentation… on
      October 7th
   –  announced Twig on my blog:
       •  http://fabien.potencier.org/article/34/templating-engines-in-php
       •  http://fabien.potencier.org/article/35/templating-engines-in-php-
          follow-up
Twig Installation
•  Download it
    –  http://github.com/fabpot/Twig/tarball/master
•  Use the Subversion repository
    –  http://svn.twig-project.org/trunk/
•  Get it on Github.com
    –  http://github.com/fabpot/twig
•  Install it via PEAR
    –  pear channel-discover pear.twig-project.org
    –  pear install twig/Twig-beta
How does Twig looks like?
Template side
                           comment
{# Twig template #}

{% for item in items %}           tag
  * {{ item.value }}          variable
{% endfor %}
                          filter
Hello {{ name|title }}

{{ items|join(', ') }}             filter with arguments
Template side
{{ item.value }}

Can be any of the following

$item['value']           mask the implementation
$item->value()
$item->getValue()
$item->value
PHP side
require_once '/path/to/Twig/Autoloader.php';
Twig_Autoloader::register();
                                      loader
$loader = new Twig_Loader_Filesystem(
     '/path/to/templates', '/path/to/cache');
$twig = new Twig_Environment($loader);
$twig->addExtension(new Twig_Extension_Escaper());
                                               extension
$template = $twig->loadTemplate('index.twig');
$params = array('name' => 'Fabien’);

$template->display($params);
Compiled template
class __TwigTemplate_5f8fa007771745904051c1db27ffc4e0 extends Twig_Template
{
  public function display(array $context)
  {                                                 compiled as a class
    // line 1
    echo "nnHello ";
                             debug information
        // line 3
        echo twig_escape_filter($this->getEnvironment(),
          (isset($context['name']) ? $context['name'] : null));
        echo "nn";

        // ...
    }
}
Template inheritance
{# Template #}
{% extends "layout.twig" %}        template extends another one
{% block title "Cool..." %}
                                          template override
{% block content %}
  Hello {{ name }}                          parent blocks
  {% parent %}
{% endblock %}          parent content
{# Layout #}
<html>
  <head>
    <title>{% block title '' %}</title>
  </head>
  <body>
    {% block content '' %}
  </body>                         define blocks with default values
</html>
Template inheritance
class __TwigTemplate_8a7c3cb36a4064e9c740c094a108a5a4 extends __TwigTemplate_c61404957758dfda283709e89376ab3e
{
  public function block_title($context)
  {
    // ...
  }

    public function block_content($context)
    {
      // ...
    }
}

class __TwigTemplate_c61404957758dfda283709e89376ab3e extends Twig_Template
{
  public function display(array $context)
  {
    echo "n <html>n     <head>n      <title>";
    $this->block_title($context);
    echo "</title>n    </head>n    <body>n      ";
    $this->block_content($context);
    echo "n    </body>n </html>";
  }

    public function block_title($context) {}

    public function block_content($context)    {}
}
Why Twig compiles templates to PHP classes?
•  Deep template inheritance becomes trivial to implement as PHP does all
   the job for us
•  Very fast in common cases
   –  For better reusability, small templates are created and included often (think
      partials in symfony)
{% for item in items %}
  * {% include "item_partial.twig" %}
{% endfor %}
   –  As each template is a stateless instance of a class,
      inclusion is just a method call away (no PHP include involved)
Macros
A macro is a reusable and configurable snippet of HTML
{# forms.twig #}
{% macro input(name, value, type, size) %}
  <input type="{{ type|default('text') }}"
    name="{{ name }}" value="{{ value|e }}"
    size="{{ size|default(20) }}" />
{% endmacro %}

{# In a template #}
{% import "forms.twig" as forms %}

{{ forms.input('username') }}
{{ forms.input('password', none, 'password') }}
Expressions
For display logic (not for business logic of course)

{% if 1 < foo < 4 and (not bar or foobar) %}
  {{ foo + 4 }}
{% endif %}
Extensibility
Extensibility
•  Everything in the core can be changed
   –  Uses dependency injection
   –  The syntax is not hardcoded
•  Built-in extension mechanism for day-to-day enhancements
   –  Adding tags
   –  Adding filters
   –  Adding node transformers
•  Extensions are used for the core features
Core extensions
•  Everything is an extension in the core

   –  Twig_Extension_Core: Provides the core features (tags and filters)


   –  Twig_Extension_Escaper: Adds automatic output-escaping and the possibility
      to escape/unescape blocks of code

   –  Twig_Extension_Sandbox: Adds a sandbox mode to the default Twig
      environment, making it safe to evaluate untrusted code
Registering an extension
•  The Core extension is automatically registered
•  Core and user extensions are managed in the same way

$twig = new Twig_Environment($loader);

$twig->addExtension(
   new Twig_Extension_Escaper()
);
Output Escaping
XSS protection
{# Manually #}
{{ post.author|escape }}               escape variable
{{ foo|escape('js') }}
                               escaping strategy
{# A whole block #}
{% autoescape on %}       escape all variables of the block
  {{ post.author }}
  {{ post.title|escape }}       won’t be double-escaped
  {{ post.html|safe }}
{% endautoescape %}     marked this as safe
{# Automatic #}
{{ post.author }}
{{ post.html|safe }}
XSS protection
•  Everything is done during compilation (see node transformers later on)

•  Nothing is decided on execution

•  No overhead between escaping by hand and auto-escaping
Sandbox
When do you need a sandbox?
•  When you need to evaluate non-trusted code; a user who can edit
   templates, typically a webmaster in a web backend
•  Security is managed by a policy instance
   (Twig_Sandbox_SecurityPolicy by default)
•  The code evaluated in a sandbox must respect the policy
•  The default policy works as follows
   –  Tags must be explicitly allowed
   –  Filters must be explicitly allowed
   –  Method calls must be explicitly allowed on a method basis
How to enable the sandbox mode?
$twig = new Twig_Environment($loader);

$tags = array('if');
$filters = array('upper');
$methods = array(
   'Article' => array('getTitle', 'getBody'),
);
$policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods);
$sandbox = new Twig_Extension_Sandbox($policy);

$twig->addExtension($sandbox);
Using the sandbox
Enable it globally

$sandbox = new Twig_Extension_Sandbox($policy, true);

Or on a template basis

{% include "user.twig" sandboxed %}
When to use Twig?
•  When users you don’t trust can edit some templates
    –  a webmaster can edit the look and feel of some templates
•  When you need to create a simple language for a domain specific problem
    –  Templates of a blog, or of an ecommerce software
•  Advantages of Twig in such cases
    –  You can use as little or as much features as you want
    –  Security
    –  Sandbox
    –  Possibility to create a DSL (a set of pre-defined tags,
       macros, and filters specific to the domain)
DSL
•  One of the goal of Twig is to provide the architecture that allows the
   developer to create its own language targeted at his specific domain
   –  Configure the syntax (delimiters)
   –  Override all built-in elements (tags, filters, …)
   –  Create your own tags, macros, and filters
•  All without having to write complex code
   –  The core classes (lexer, parser, and compiler) provides a simple API to let you do
      your job without understanding the nitty-gritty details of the internals
Under the hood
From a template to a PHP file
                                  Request
    Something decide which template to render (typically a controller)
                  if already compiled in cache (on the filesystem)
Twig_Loader

                               Template source (string)             happens once
Twig_Lexer                     Stream of tokens (Twig_Token)                 even faster
Twig_Parser                    Tree of nodes (Twig_Node)               if APC is enabled

Twig_Compiler
                               Compiled template (PHP class)

                                              HTML
The lexer
The lexer tokenizes the template source and returns a stream of tokens
$stream =
  $twig->tokenize('Hello {{ name|title }}');
echo $stream;

TEXT_TYPE(Hello )
VAR_START_TYPE()
NAME_TYPE(name)
VAR_END_TYPE()
EOF_TYPE()
The parser
The parser converts the stream of tokens into a tree of nodes
$nodes= $twig->parse($stream);
echo $nodes;

Twig_Node_Module(
  Twig_Node_Text(Hello )
  Twig_Node_Print(
    Twig_Node_Expression_Name(name)
  )
)
The parser
// with automatic output escaping
Twig_Node_Module(              added by manipulating
  Twig_Node_Text(Hello )              the AST
  Twig_Node_Print(
    Twig_Node_Expression_Filter(
      Twig_Node_Expression_Name(name)
      (escape())
    )
  )
)
Node transformer classes
•  Manipulate the AST (Abstract Syntax Tree), the tree of nodes, before
   compilation
•  Each transformer can visit the tree and do something with each node
   –  remove it
   –  visit its children
   –  change it by another node
   –  wrap it (with a filter for instance)
Node transformer classes
•  Used by the core extensions
   –  Escaper
       •  adds the escape filter to Twig_Node_Print nodes
       •  except when the node is already filtered with escape (to avoid double-escaping), or
          already filtered with safe (to avoid escaping safe HTML strings)
   –  Sandbox
       •  To collect calls to filters and tags in a template
   –  Filter blocks
       •  To apply a set of filters to a whole block
The compiler
    The compiler eventually converts the tree of nodes to PHP code
class __TwigTemplate_5f8fa007771745904051c1db27ffc4e0 extends Twig_Template
{
  public function display(array $context)
  {
    // line 1
    echo "Hello ";

        echo (isset($context['name']) ? $context['name'] : null);
    }
}
Integration
Integration with other frameworks
•  symfony
    –  sfTwigPlugin
•  Zend Framework
    –  http://svn.twig-project.org/branches/zend_adapter/

•  Yii
    –  http://www.yiiframework.com/extension/twig-view-renderer/

•  Kohana
    –  http://github.com/shadowhand/kohana-twig

•  … and more to come
Questions?
Sensio S.A.
    92-98, boulevard Victor Hugo
        92 115 Clichy Cedex
              FRANCE
       Tél. : +33 1 40 99 80 80

               Contact
           Fabien Potencier
    fabien.potencier at sensio.com




  http://www.sensiolabs.com/
http://www.symfony-project.org/
 http://fabien.potencier.org/

More Related Content

What's hot

Making Sense of Twig
Making Sense of TwigMaking Sense of Twig
Making Sense of TwigBrandon Kelly
 
PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021Ayesh Karunaratne
 
PHP Functions & Arrays
PHP Functions & ArraysPHP Functions & Arrays
PHP Functions & ArraysHenry Osborne
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?Nikita Popov
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)James Titcumb
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?Nikita Popov
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Fabien Potencier
 
PHP 8.1 - What's new and changed
PHP 8.1 - What's new and changedPHP 8.1 - What's new and changed
PHP 8.1 - What's new and changedAyesh Karunaratne
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5 Wildan Maulana
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Fwdays
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I thinkWim Godden
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance TriviaNikita Popov
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Class 2 - Introduction to PHP
Class 2 - Introduction to PHPClass 2 - Introduction to PHP
Class 2 - Introduction to PHPAhmed Swilam
 

What's hot (20)

Making Sense of Twig
Making Sense of TwigMaking Sense of Twig
Making Sense of Twig
 
PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021
 
Design patterns in PHP
Design patterns in PHPDesign patterns in PHP
Design patterns in PHP
 
PHP Functions & Arrays
PHP Functions & ArraysPHP Functions & Arrays
PHP Functions & Arrays
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3
 
PHP 8.1 - What's new and changed
PHP 8.1 - What's new and changedPHP 8.1 - What's new and changed
PHP 8.1 - What's new and changed
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Functions in PHP
Functions in PHPFunctions in PHP
Functions in PHP
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"
 
Sorting arrays in PHP
Sorting arrays in PHPSorting arrays in PHP
Sorting arrays in PHP
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
 
New in php 7
New in php 7New in php 7
New in php 7
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Class 2 - Introduction to PHP
Class 2 - Introduction to PHPClass 2 - Introduction to PHP
Class 2 - Introduction to PHP
 

Similar to Twig, the flexible, fast, and secure template language for PHP

Use Symfony2 components inside WordPress
Use Symfony2 components inside WordPress Use Symfony2 components inside WordPress
Use Symfony2 components inside WordPress Maurizio Pelizzone
 
Twig for Drupal @ Frontendunited Amsterdam 2012
Twig for Drupal @ Frontendunited Amsterdam 2012Twig for Drupal @ Frontendunited Amsterdam 2012
Twig for Drupal @ Frontendunited Amsterdam 2012Rene Bakx
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and DesktopElizabeth Smith
 
Thymeleaf and Spring Controllers.ppt
Thymeleaf and Spring Controllers.pptThymeleaf and Spring Controllers.ppt
Thymeleaf and Spring Controllers.pptPatiento Del Mar
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Hugo Hamon
 
Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Ted Kulp
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017Amanda Giles
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2Elizabeth Smith
 
TYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkTYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkChristian Trabold
 
The Way to Theme Enlightenment
The Way to Theme EnlightenmentThe Way to Theme Enlightenment
The Way to Theme EnlightenmentAmanda Giles
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy CodeRowan Merewood
 
Building Potent WordPress Websites
Building Potent WordPress WebsitesBuilding Potent WordPress Websites
Building Potent WordPress WebsitesKyle Cearley
 
WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1Yoav Farhi
 
Writing and Publishing Puppet Modules
Writing and Publishing Puppet ModulesWriting and Publishing Puppet Modules
Writing and Publishing Puppet ModulesPuppet
 

Similar to Twig, the flexible, fast, and secure template language for PHP (20)

Use Symfony2 components inside WordPress
Use Symfony2 components inside WordPress Use Symfony2 components inside WordPress
Use Symfony2 components inside WordPress
 
Twig for Drupal @ Frontendunited Amsterdam 2012
Twig for Drupal @ Frontendunited Amsterdam 2012Twig for Drupal @ Frontendunited Amsterdam 2012
Twig for Drupal @ Frontendunited Amsterdam 2012
 
Extending Twig
Extending TwigExtending Twig
Extending Twig
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
 
Tornadoweb
TornadowebTornadoweb
Tornadoweb
 
Thymeleaf and Spring Controllers.ppt
Thymeleaf and Spring Controllers.pptThymeleaf and Spring Controllers.ppt
Thymeleaf and Spring Controllers.ppt
 
Twig
TwigTwig
Twig
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Seven deadly theming sins
Seven deadly theming sinsSeven deadly theming sins
Seven deadly theming sins
 
The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2
 
TYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkTYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase framework
 
The Way to Theme Enlightenment
The Way to Theme EnlightenmentThe Way to Theme Enlightenment
The Way to Theme Enlightenment
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
Building Potent WordPress Websites
Building Potent WordPress WebsitesBuilding Potent WordPress Websites
Building Potent WordPress Websites
 
WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1
 
Writing and Publishing Puppet Modules
Writing and Publishing Puppet ModulesWriting and Publishing Puppet Modules
Writing and Publishing Puppet Modules
 

More from Fabien Potencier

Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Fabien Potencier
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Fabien Potencier
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 

More from Fabien Potencier (20)

Varnish
VarnishVarnish
Varnish
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 

Recently uploaded

JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard37
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxFIDO Alliance
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaWSO2
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
ChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps ProductivityChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps ProductivityVictorSzoltysek
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingScyllaDB
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxFIDO Alliance
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....rightmanforbloodline
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxFIDO Alliance
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsLeah Henrickson
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptxFIDO Alliance
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...FIDO Alliance
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceIES VE
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctBrainSell Technologies
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 

Recently uploaded (20)

JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptx
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
ChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps ProductivityChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps Productivity
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream Processing
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptx
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...Hyatt driving innovation and exceptional customer experiences with FIDO passw...
Hyatt driving innovation and exceptional customer experiences with FIDO passw...
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational Performance
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage Intacct
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 

Twig, the flexible, fast, and secure template language for PHP

  • 1. Twig The flexible, fast, and secure template language for PHP Fabien Potencier
  • 2. Fabien Potencier •  Serial entrepreneur and developer by passion •  Founder of Sensio –  Web Agency (France and USA) –  Since 1998 –  70 people –  Open-Source Specialists –  Big corporate customers –  Consulting, training, development, web design, … and more –  Sponsor of a lot of Open-Source projects like symfony and Doctrine
  • 3. Fabien Potencier •  Creator and lead developer of symfony… •  and creator and lead developer of some more: –  symfony components –  Swift Mailer : Powerful component based mailing library for PHP –  Twig : Fexible, fast, and secure template language for PHP –  Pirum : Simple PEAR Channel Server Manager –  Sismo : PHP continuous integration server –  Lime : Easy to use unit testing library for PHP –  Twitto : A web framework in a tweet –  Twittee : A Dependency Injection Container in a tweet –  Pimple : A small PHP 5.3 dependency injection container
  • 4. Fabien Potencier •  Read my technical blog: http://fabien.potencier.org/ •  Follow me on Twitter: @fabpot •  Fork my code on Github: http://github.com/fabpot/
  • 6. Twig history I was looking for a good template engine I don’t like to reinvent the wheel I started to look around for existing ones
  • 7. Twig history But I found none that satisfied all my personal needs: –  Fast (templates should be compiled to PHP) –  Secure (flexible output escaping) –  Sandboxed (whitelist system) –  Not tied to only HTML templates (emails, …) –  Syntax similar to Django & Jinja (but flexible, nothing hardcoded) –  Embeddable –  “Modern” features (such as template inheritance) –  Easily extensible (should be able to override everything) –  Clean OO code (“real” lexer, parser, and compiler, DI)
  • 8. Twig history •  … except Twig, which was quite close and had a solid architecture –  written by Armin Ronacher (of Jinja fame – a python template engine) •  … but –  not available as a standalone project (packaged with chypr, a blog platform) –  never really maintained •  I stumbled upon it by chance
  • 9. Twig history •  I started hacking the code, found it immediately beautiful and flexible •  I wrote an email to Armin •  and I took over the maintenance of it –  I’m the lead developer since October 1st –  kept the source under a BSD license –  created a dedicated website, mailing-list, wrote some documentation… on October 7th –  announced Twig on my blog: •  http://fabien.potencier.org/article/34/templating-engines-in-php •  http://fabien.potencier.org/article/35/templating-engines-in-php- follow-up
  • 10. Twig Installation •  Download it –  http://github.com/fabpot/Twig/tarball/master •  Use the Subversion repository –  http://svn.twig-project.org/trunk/ •  Get it on Github.com –  http://github.com/fabpot/twig •  Install it via PEAR –  pear channel-discover pear.twig-project.org –  pear install twig/Twig-beta
  • 11. How does Twig looks like?
  • 12. Template side comment {# Twig template #} {% for item in items %} tag * {{ item.value }} variable {% endfor %} filter Hello {{ name|title }} {{ items|join(', ') }} filter with arguments
  • 13. Template side {{ item.value }} Can be any of the following $item['value'] mask the implementation $item->value() $item->getValue() $item->value
  • 14. PHP side require_once '/path/to/Twig/Autoloader.php'; Twig_Autoloader::register(); loader $loader = new Twig_Loader_Filesystem( '/path/to/templates', '/path/to/cache'); $twig = new Twig_Environment($loader); $twig->addExtension(new Twig_Extension_Escaper()); extension $template = $twig->loadTemplate('index.twig'); $params = array('name' => 'Fabien’); $template->display($params);
  • 15. Compiled template class __TwigTemplate_5f8fa007771745904051c1db27ffc4e0 extends Twig_Template { public function display(array $context) { compiled as a class // line 1 echo "nnHello "; debug information // line 3 echo twig_escape_filter($this->getEnvironment(), (isset($context['name']) ? $context['name'] : null)); echo "nn"; // ... } }
  • 16. Template inheritance {# Template #} {% extends "layout.twig" %} template extends another one {% block title "Cool..." %} template override {% block content %} Hello {{ name }} parent blocks {% parent %} {% endblock %} parent content {# Layout #} <html> <head> <title>{% block title '' %}</title> </head> <body> {% block content '' %} </body> define blocks with default values </html>
  • 17. Template inheritance class __TwigTemplate_8a7c3cb36a4064e9c740c094a108a5a4 extends __TwigTemplate_c61404957758dfda283709e89376ab3e { public function block_title($context) { // ... } public function block_content($context) { // ... } } class __TwigTemplate_c61404957758dfda283709e89376ab3e extends Twig_Template { public function display(array $context) { echo "n <html>n <head>n <title>"; $this->block_title($context); echo "</title>n </head>n <body>n "; $this->block_content($context); echo "n </body>n </html>"; } public function block_title($context) {} public function block_content($context) {} }
  • 18. Why Twig compiles templates to PHP classes? •  Deep template inheritance becomes trivial to implement as PHP does all the job for us •  Very fast in common cases –  For better reusability, small templates are created and included often (think partials in symfony) {% for item in items %} * {% include "item_partial.twig" %} {% endfor %} –  As each template is a stateless instance of a class, inclusion is just a method call away (no PHP include involved)
  • 19. Macros A macro is a reusable and configurable snippet of HTML {# forms.twig #} {% macro input(name, value, type, size) %} <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> {% endmacro %} {# In a template #} {% import "forms.twig" as forms %} {{ forms.input('username') }} {{ forms.input('password', none, 'password') }}
  • 20. Expressions For display logic (not for business logic of course) {% if 1 < foo < 4 and (not bar or foobar) %} {{ foo + 4 }} {% endif %}
  • 22. Extensibility •  Everything in the core can be changed –  Uses dependency injection –  The syntax is not hardcoded •  Built-in extension mechanism for day-to-day enhancements –  Adding tags –  Adding filters –  Adding node transformers •  Extensions are used for the core features
  • 23. Core extensions •  Everything is an extension in the core –  Twig_Extension_Core: Provides the core features (tags and filters) –  Twig_Extension_Escaper: Adds automatic output-escaping and the possibility to escape/unescape blocks of code –  Twig_Extension_Sandbox: Adds a sandbox mode to the default Twig environment, making it safe to evaluate untrusted code
  • 24. Registering an extension •  The Core extension is automatically registered •  Core and user extensions are managed in the same way $twig = new Twig_Environment($loader); $twig->addExtension( new Twig_Extension_Escaper() );
  • 26. XSS protection {# Manually #} {{ post.author|escape }} escape variable {{ foo|escape('js') }} escaping strategy {# A whole block #} {% autoescape on %} escape all variables of the block {{ post.author }} {{ post.title|escape }} won’t be double-escaped {{ post.html|safe }} {% endautoescape %} marked this as safe {# Automatic #} {{ post.author }} {{ post.html|safe }}
  • 27. XSS protection •  Everything is done during compilation (see node transformers later on) •  Nothing is decided on execution •  No overhead between escaping by hand and auto-escaping
  • 29. When do you need a sandbox? •  When you need to evaluate non-trusted code; a user who can edit templates, typically a webmaster in a web backend •  Security is managed by a policy instance (Twig_Sandbox_SecurityPolicy by default) •  The code evaluated in a sandbox must respect the policy •  The default policy works as follows –  Tags must be explicitly allowed –  Filters must be explicitly allowed –  Method calls must be explicitly allowed on a method basis
  • 30. How to enable the sandbox mode? $twig = new Twig_Environment($loader); $tags = array('if'); $filters = array('upper'); $methods = array( 'Article' => array('getTitle', 'getBody'), ); $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods); $sandbox = new Twig_Extension_Sandbox($policy); $twig->addExtension($sandbox);
  • 31. Using the sandbox Enable it globally $sandbox = new Twig_Extension_Sandbox($policy, true); Or on a template basis {% include "user.twig" sandboxed %}
  • 32. When to use Twig? •  When users you don’t trust can edit some templates –  a webmaster can edit the look and feel of some templates •  When you need to create a simple language for a domain specific problem –  Templates of a blog, or of an ecommerce software •  Advantages of Twig in such cases –  You can use as little or as much features as you want –  Security –  Sandbox –  Possibility to create a DSL (a set of pre-defined tags, macros, and filters specific to the domain)
  • 33. DSL •  One of the goal of Twig is to provide the architecture that allows the developer to create its own language targeted at his specific domain –  Configure the syntax (delimiters) –  Override all built-in elements (tags, filters, …) –  Create your own tags, macros, and filters •  All without having to write complex code –  The core classes (lexer, parser, and compiler) provides a simple API to let you do your job without understanding the nitty-gritty details of the internals
  • 35. From a template to a PHP file Request Something decide which template to render (typically a controller) if already compiled in cache (on the filesystem) Twig_Loader Template source (string) happens once Twig_Lexer Stream of tokens (Twig_Token) even faster Twig_Parser Tree of nodes (Twig_Node) if APC is enabled Twig_Compiler Compiled template (PHP class) HTML
  • 36. The lexer The lexer tokenizes the template source and returns a stream of tokens $stream = $twig->tokenize('Hello {{ name|title }}'); echo $stream; TEXT_TYPE(Hello ) VAR_START_TYPE() NAME_TYPE(name) VAR_END_TYPE() EOF_TYPE()
  • 37. The parser The parser converts the stream of tokens into a tree of nodes $nodes= $twig->parse($stream); echo $nodes; Twig_Node_Module( Twig_Node_Text(Hello ) Twig_Node_Print( Twig_Node_Expression_Name(name) ) )
  • 38. The parser // with automatic output escaping Twig_Node_Module( added by manipulating Twig_Node_Text(Hello ) the AST Twig_Node_Print( Twig_Node_Expression_Filter( Twig_Node_Expression_Name(name) (escape()) ) ) )
  • 39. Node transformer classes •  Manipulate the AST (Abstract Syntax Tree), the tree of nodes, before compilation •  Each transformer can visit the tree and do something with each node –  remove it –  visit its children –  change it by another node –  wrap it (with a filter for instance)
  • 40. Node transformer classes •  Used by the core extensions –  Escaper •  adds the escape filter to Twig_Node_Print nodes •  except when the node is already filtered with escape (to avoid double-escaping), or already filtered with safe (to avoid escaping safe HTML strings) –  Sandbox •  To collect calls to filters and tags in a template –  Filter blocks •  To apply a set of filters to a whole block
  • 41. The compiler The compiler eventually converts the tree of nodes to PHP code class __TwigTemplate_5f8fa007771745904051c1db27ffc4e0 extends Twig_Template { public function display(array $context) { // line 1 echo "Hello "; echo (isset($context['name']) ? $context['name'] : null); } }
  • 43. Integration with other frameworks •  symfony –  sfTwigPlugin •  Zend Framework –  http://svn.twig-project.org/branches/zend_adapter/ •  Yii –  http://www.yiiframework.com/extension/twig-view-renderer/ •  Kohana –  http://github.com/shadowhand/kohana-twig •  … and more to come
  • 45. Sensio S.A. 92-98, boulevard Victor Hugo 92 115 Clichy Cedex FRANCE Tél. : +33 1 40 99 80 80 Contact Fabien Potencier fabien.potencier at sensio.com http://www.sensiolabs.com/ http://www.symfony-project.org/ http://fabien.potencier.org/