Six Reasons Why Twig Makes My Life Better

On Wednesday 16 March 2011 in Symfony, PHP / AFUP, Best practices

Template engines are really famous in the PHP World nowadays. As of today, I always disliked template engines written in PHP and I always advocated to use pure PHP templates to generate views.

Some of you still probably follow the same opinion. In fact PHP sucks as a template engine. Why? Because PHP is so much verbose, PHP doesn't support automatic output escaping and modern templating features, PHP doesn't ease separation of concerns (aka MVC architecture)... Of course, there is Twig to the rescue! A modern and powerful template engine you will love.

Most of well-known templating engine libraries also suck for many reasons. They mainly offer a very restricted syntax (only variables and loops) and they are not secure and flexible. They are also slow and not efficient as they don't cache anything and exploit regular expressions when parsing a template. So, what to do? Twig to the rescue!

My point of view about template engines has changed today since I use Twig with Symfony2 and I will give six main reasons why I really like Twig. Twig is a modern template engine written in PHP 5.2 by Fabien Potencier and sponsored by Sensio Labs, the company behind the Symfony framework. Twig offers a secure, concise and full featured API inherited from the famous Django Jinja templates in Python. But what makes Twig so powerful?

Twig is easy to learn!

First of all, Twig offers a really concise and easy to learn syntax based on three tags to remember. The {{ }} tag displays something, the {% %} evaluates an expression like a loop or a condition and the {# #} finally comments code blocks.

{# This is a commented line #}
 
{% if age > 18 %}
    Your age is {{ age }} and you can enter this site.
{% else %}
    Sorry dude but you must be older to enter this site.
{% endif %}

When it comes to output, Twig brings a nice API to render variables. Whatever variable type is (scalar, array or object), Twig tries to determine how to get the value whereas the end user syntax remains identical.

{{ user.firstName }}

The above snippet renders the first name of a user variable. Here, the user variable can be an associative array or an object. If it's an object, Twig tries to call a public property, a method or a getter method.

The Twig learning curve is really weak. In a couple of days, developers and web designers will be able to work on the same code base and speak the same language. At Sensio, both developers and HTML/CSS designers use Twig as the common speak. And believe me, web designers love speaking Twig instead of PHP echos.

Twig is secure!

When it comes to output escaping, PHP definitively sucks as you have to escape variables by yourselves wit functions like htmlspecialchars() or htmlentities(). That makes your code completely verbose and difficult to maintain. What if you forget to escape a dangerous variable? You might endorse a security breach (XSS for example) if this variable value comes from the end user.

Twig brings automatic output escaping by default, so that you don't need to escape variables by hand. Of course, the API is so flexible that you can have access to the raw variable content if necessary and if you are aware of your application security.

{# The variable is auto escaped #}
{{ article.content }}
 
{# The variable is not double escaped by the filter #}
{{ article.content|e }}
 
{# The variable is not escaped #}
{{ article.content|raw }}

Not only variables can be escaped. Indeed, you can escape a whole HTML block or leave it raw if you want.

{% autoescape true %}
<ul>
    <li>Escape this unordered list</li>
</ul>
{% endautoescape %}
 
{% raw %}
<ul>
    <li>Leave this list raw</li>
</ul>
{% endraw %}

As you can see, the API remains concise and templates easy to read and maintain. You are not still convinced? Keep reading this article to discover lots of new modern features.

Twig is full featured!

Compared to other template engine libraries, Twig brings a rich API with modern features. For instance, Twig supports a for loop, an if statement to perform decisions, logical, maths and comparision operators.

{% if name == 'Hugo' %}
    Welcome Hugo!
{% endif %}
 
{% for fruit in ['apple', 'banana', 'strawberry', 'pear'] %}
  * {{ fruit }}
{% else %}
  * No fruit to display...
{% endfor %}

Modern features you said? You kidding! No I don't! Twig has some real cool modern features. Look at the previous for loop and its else clause. That's a killer feature.

One of my favorite advanced tool is template inheritance. Basically, a template can extend another template and there is no limitations with the inheritance hierarchy.

Below is the template code for a base.html.twig layout...

{# base.html.twig #}
 
<html>
    <head>
        <title>{% block title %}Welcome on my website{% endblock %}</title>
    </head>
    <body>
        <h1>Hugo Hamon</h1>
        {% block body %}{% endblock %}
    </body>
</html>

... and the one of a resume.html.twig template that extends the previous one.

{# resume.html.twig #}
 
{% extends "base.html.twig" %}
 
{% block title %}
    Curriculum Vitae - Symfony2 web developer.
{% endblock %}
 
{% block body %}
    Below are listed my skills and education.
 
    <h2>Skills</h2>
 
    <ul>
        <li>PHP 5.3</li>
        <li>MySQL</li>
        <li>Symfony framework</li>
    </ul>
 
    <h2>Education</h2>
 
    {% include 'education.html.twig' %}
 
{% endblock %}

In the above example, the resume.html.twig template extends the base.html.twig. It defines two block contents (title and body) that will fill the two identical blocks in the parent template to reassemble the whole HTML page. Nice isn't it? Imagine that you can make the resume.html.twig inherit from an intermediate template that extends the base.html.twig template.

The resume.html.twig also includes a template fragment called education.html.twig thanks to the include keyword.

Twig also brings a bunch of filters and functions. A filter is a function that modifies a variable value. Filters can be chained thanks to the pipe character, |, to make the code more readable.

{{ '<strong>hello world</strong>'|striptags|upper }}

A function is like a global php function that performs some business logic. One of the most interesting function is the cycle() function that returns a value from an array depending on a counter value.

{% for i in 0..10 %}
    <span class="{{ cycle(['odd', 'even'], i) }}">
        Current number is {{ i }}
    </span>
{% endfor %}

One of the greatest features of Twig are macros. A macro is like a php function that you can define and call from a template or another macro. Basically, a macro performs some small presentation logic like generating a button.

{% macro input(name, value, type, size) %}
    <input type="{{ type|default('text') }}" 
        name="{{ name }}" 
        value="{{ value|e }}" 
        size="{{ size|default(20) }}" />
{% endmacro %}
 
<p>{{ forms.input('username') }}</p>
<p>{{ forms.input('password', none, 'password') }}</p>

Are you convinced now? I hope so. Just have a look to the official documentation of Twig on twig-project.org to discover some other hidden cool features.

Twig is fast... really!

Although Twig has a full featured API, you may probably think that it's slow. It must take lots of time to parse and render such templates. You're wrong! Twig isn't slow at all! Why and how?

Twig is a clever template engine. It compiles templates down to plain PHP classes and stores the raw result in a cached file. That way, Twig templates aren't parsed twice.

In October 2009, Fabien realized a couple of benchmarks to compare Twig to other well-known template engine libraries. At this moment, Twig already announced incredible performances whereas it wasn't entirely finished.

Twig is flexible and extensible!

Still not convinced by the power of Twig? You won't after this argument. Twig is so flexible that it can be extended at will. Changing tags to use brackets instead of braces is as simple as overriding a core class. Adding a new filter, function or test is also a piece of cake. You just need to create a new extension class and implement a couple of mandatory methods.

The example below shows how to register a new truncate filter and a new nl2br() global function.

class Text_Twig_Extension extends Twig_Extension
{
    public function getName()
    {
        return 'text';
    }
 
    public function getFilters()
    {
        return array(
            'truncate' => new \Twig_Filter_Method($this, 'truncate')
        );
    }
 
    public function truncate($text, $max = 30)
    {
        $lastSpace = 0;
 
        if (strlen($text) >= $max)
        {
            $text = substr($text, 0, $max);
            $lastSpace = strrpos($text,' ');
            $text = substr($text, 0, $lastSpace).'...';
        }
 
        return $text;
    }
 
    public function getFunctions()
    {
        return array(
            'nl2br' => \Twig_Function_Method($this, 'nl2br', array('is_safe' => array('html'))) 
        );
    }
 
    public function nl2br($text)
    {
        return nl2br($text);
    }
}

They are both then used as below from a Twig template.

{% set text = 'A super long string that I want to truncate up to 20 characters...' %}
{{ text|truncate(20) }}
 
{% set text = "A text with multiple lines.\n\nThey must be changed to <br/>" %}
{{ nl2br(text) }}

That makes Twig so powerful and professional against the other template engines. You can add your own features set to Twig and customize its API as you wish. This is possible because Twig runs a powerful Lexer parser. Last but not least, Twig has an incredible error management and syntax analyser. Debugging a template hasn't be so easy with Twig.

Twig is "enterprise ready"!

The main goal of a template engine is to separate the business logic from the view and make websites more maintainable and evolutive. Template engines also facilitate team work by providing a common language between developers and web designers.

With its simple, concise and easy to learn syntax, Twig helps developers and web designers to be more productive. They conceive clean templates and write them fast. At Sensio, we already took benefits by leveraging the power of Twig. Web designers learnt Twig in a couple of days and now use it daily.

Twig is "enterprise ready". It's fully unit tested and well documented. The new Symfony framework has already integrated Twig as its default presentation layer and encourages developers to switch from PHP to Twig.

As you can see, Twig really makes my life easier and better as a webdeveloper and I strongly encourage you to give it a try. You will love it and adopt it for your future developments. I bet!

Comments

Posted by Tim - about 1 year ago

I shared your opinion on php template stuff, and I have to admit I change my mind too when I tried Twig.

It's really amazing to use it and to extend it!

Posted by Maxime - about 1 year ago

Used to eZ Templating, I'm so pissed off Fabien Potencier used Twig in sf2. As Fabien said in his benchmark article http://bit.ly/lOnJU, eZ Templates is full of features: it's great ! Except that it's not.

The main problem of templating is:
- you have so much features so the syntax becomes more complicated to read than php. Then why ain't you using php ?
- you don't have enough features. You'll have then to implement yourself the requested feature so you can use it in your template. So why ain't you using php at first ?

PHP was already a template language at the begining. And then, they had many features, so you had to use another templating layer. How many layers will you add before being satisfied ?

By the way, I don't agree with your 6 reasons.

1- Twig is easy to learn!
Except that if you're using symfony2, you already know PHP. Anyway, every template language is easy to learn... (as far as I know)

2- Twig is secure!
Yes, but you have more inconveniences. Less control on your data than you'd have with PHP.

3- Twig is full featured!
Definitely not as much as PHP.

4- Twig is fast... really!
Since you're developing in PHP, you're aware of performance problems and you are using APC and others cache tools like Varnish. So will you really need a fast template language ?

5- Twig is flexible and extensible!
If you have to add a new functionnality (such as another template function), you will develop it in PHP. If you were already using PHP, you wouldn't had to. So in the end, you lost some time.

6- Twig is "enterprise ready"!
That is the point which I don't disagree. But you'll have to pay attention to you Web designer ! A Web Designer who doesn't know how it works inside is able to develop very bad things. Inheritance, "else clause" in a loop,... are many powerful (but complicated to understand) tools with which you can hide huge bugs. And then the PHP developper will have to come to rescue the Web Designer and help him correcting the bug. In the end, is it really saving time ?

Posted by l3l0 - about 1 year ago

Hello Maxime.

I think that PHP is great for templating but...
allows to use many (all) features, mixing business logic with the template code, and allows for other nasty things. So maybe better to use a template's framework which has fewer features but does not allow for doing bad and ugly things

About those points:
1. Twig is easy to learn!
I am PHP developer and I know how to use PHP but Web Designers do not need to understand the code. I think that twig and other template engines can helps others people to understand.
So I think it is easy to learn (for all not only for devs)

2. Twig is secure!
I disagree. You have more control than in PHP templates, you can define possible filters/functions, so You can decide which functions can be used and which can't be used in templates. (more strict API)

3. Twig is full featured!
I agree, definitely not as much as PHP. Although I think it's better, see one point above. I think that Twig features are sufficent.

4. Twig is fast... really!
I agree, it is not so important.

5. Twig is flexible and extensible!
I agree, in PHP I wouldn't have to add new feature so offten, but in Twig I have strict API and control so if I need something new I can add it easliy.

6. Twig is "enterprise ready"!
In PHP templates Web designer can do everything, so it not the point for me.

Regads l3l0

Posted by Hugo Hamon - about 1 year ago

Hi Maxime,

Thank you for your interesting answer about my point of view. Let me explain my mind in depth about what you point out.

> you have so much features so the syntax becomes more complicated to read than php. Then why ain't you using php ?

PHP sucks when it comes to template engine because it does not support output escaping by default. That's the main problem. Moreover, PHP is verbose and it's not easy to learn and use for a web designer.

Finally, you can't restrict the API when dealing with pure PHP templates. As l3l0 said, authorizing the full PHP API leads to bad things like business logic in templates. That's why we can find templates using functions like mysql_query() in PHP applications...

> Except that if you're using symfony2, you already know PHP. Anyway, every template language is easy to learn... (as far as I know)

All template engines are almost easy to learn but most of them have a crappy syntax that makes template code not easy to maintain or to read. Simple does not mean clean!

I'm also pretty sure that thanks to Symfony2, we will have in the next few months a repository of Twig extensions to download.

> 1- Twig is easy to learn!
> you don't have enough features. You'll have then to implement yourself the requested feature so you can use it in your template. So why ain't you using php at first ?

Twig offers a very large features set that fit most of templating needs (echoing variables, looping over a collection, making decisions...). Most of template engines support that but when you need to add more features you are generaly blocked. With Twig, it's really easy to add new features to the API. You just need to create an extension class with a couple of methods.

> 2- Twig is secure!
> Yes, but you have more inconveniences. Less control on your data than you'd have with PHP.

That's wrong. You have a full control of your data with Twig as you can decide if you want to get an escaped value or a raw value. Moreover, you can apply plenty of built-in functions and filters on your data to format them. I didn't meet such a case where I might lose the control of my data.

>3- Twig is full featured!
>Definitely not as much as PHP.

Having the full PHP API available does not mean that you can use everything from your templates. If you follow best practices, templating is just echoing and formatting data coming from the model. That's why you don't need a giant API of functions. The Twig native API is mainly usable enough to help you build your templates. If you need to run PHP functions that don't echo and format data in your templates, that's probably a design problem in your application.

>4- Twig is fast... really!
>Since you're developing in PHP, you're aware of performance problems and you are using APC and others cache tools like Varnish. So will you really need a fast template language ?

That's not a major problem and I almost agree with you for that. But comparing to other template engines, some of them don't cache anything and parse templates at every coming request. So, even if you have APC enabled, they will regenerate the content everytime. That has an important impact on your CPU consumption and the number of pages your server can deliver. If your CPU is busy, you can't serve someone else.

Concerning Varnish, you're right. Installing a reverse proxy cache gives an incredible boost to your page load. But in reality, how many developers do you think they are using Varnish nowadays? Not that much...

>5- Twig is flexible and extensible!
>If you have to add a new functionnality (such as another template function), you will develop it in PHP. If you were already using PHP, you wouldn't had to. So in the end, you lost some time.

Well you're right but the time you lost is very minimal as creating a new Twig extension implies to create a class and a couple of methods. As everything is well documented, you will probably copy / paste the documentation... So, finally you don't lose so much time to extend Twig.

Hugo.

Posted by Emiliano Viada - about 1 year ago

Great post Hugo!! I love Twig and this post explain very clear why..

Cheers.

Posted by desfrenes - 11 months ago

I think it's worth saying that Twig is more or less a PHP port of the nice Jinja package for Python, which is included in the great Flask microframework.

Posted by Han Chung - 5 months ago

If anyone in interested in testing out twig, I have created a demo web app for people to test it at demo.codefunc.com

Cheers!

Posted by Sudheesh - 2 months ago

Can anybody help me in adding multiple macros in a single Twig file?

Posted by vana - about 1 month ago

When it comes to output escaping, PHP definitively sucks as you have to escape variables by yourselves wit functions like htmlspecialchars() or htmlentities(). That makes your code completely verbose and difficult to maintain. What if you forget to escape a dangerous variable? You might endorse a security breach (XSS for example) if this variable value comes from the end user.

yes, you are suck
that complaining irrevant problem, you just make another layer of complexity.

Posted by Hugo Hamon - about 1 month ago

@Vana If you give a try to Twig one day, you will see that it eases your life. I agree that a template engine adds a small layer of complexity to your application. But it's a useful complexity if it allows you to save coding, debugging and maintenance time. Also Twig comes with lots of features, a concise syntax, and the capability to be extended easily. As I already said, Twig also escapes your variables.

In Twig, you will write this:

{{ article.title }}

Whereas in PHP, you will have to write:

<?php echo htmlspecialchars($article->title, ENT_QUOTES, 'utf-8') ?>

It's a huge piece of code to write everytime you want to output a variable. Ok you can simplify this code with a function like this:

function e($str)
{
return htmlspecialchars($str, ENT_QUOTES, 'utf-8');
}

One of the most interesting part of Twig is the variable abstraction. In Twig, you simply write this:

{{ article.title }}

Which is equivalent to:

<?php echo e( $article['title'] ) ?>
<?php echo e( $article->title ) ?>
<?php echo e( $article->title() ) ?>
<?php echo e( $article->getTitle() ) ?>
<?php echo e( $article->isTitle() ) ?>

So, with Twig you can switch from a regular object to an array or vice-versa without changing your templates. If you do that in PHP, you will have to change your templates or add ugly __get(), __call() and ArrayAccess hacks everywhere in your code. Magic methods adds lots of overhead and complexity to the code ;)

Cheers.

Posted by vana - about 1 month ago

ok as a programmer that says twig make your life easier thus
{{ article.title }}
that is a variable abstraction,

--> how can i make sure that, the _article_ is an array, or an object with properties title, or an object with method name title() or getTitle() or isTitle() ? how we can make sure ?

"So, with Twig you can switch from a regular object to an array or vice-versa without changing your templates."
does it really make sense to do this way ? if you change your programming logic, making change the way for representating data, you must adjust your template to the right way.

Posted by Hugo Hamon - about 1 month ago

> how can i make sure that, the _article_ is an array, or an object with properties title, or an object with method name title() or getTitle() or isTitle() ? how we can make sure ?

You don't care about knowing if "article" is an array or an object. At this point you're in the view and you just want to display data. Twig comes with naming conventions and "article.title" can be an associative array or an object with a public property, or title(), getTitle() and isTitle() methods. If one of these methods exist in the object, Twig will call it.

> does it really make sense to do this way ? if you change your programming logic, making change the way for representating data, you must adjust your template to the right way.

Yes it does make sens. A good example is the following. In your application, you start using objects to store your data. After several months in production, your application becomes very popular and runs a bit slower. So, it's time to optimize the application and you want to remove objects in favor of array. With Twig and its variable abstraction you can switch from a way to another without changing a single line of code in your templates.

Twig does not read your templates everytime. They are compiled down to pure PHP classes, so there is no performance impact compared to a typical PHP template.

Just try it and you will love it!

Posted by Thomas Decaux - about 1 month ago

My experience with Twig : need to learn something new, twig has maybe less than 20 Php funtions built in ... so took so many time to rewrite everything ....

And Twig is slow... (slower than Smary 3, much slower than Php), if you care about performance, no way to use a template engine!

I am still using it, still reading documentation everytime... nice to lose time ...

Posted by Hugo Hamon - about 1 month ago

@Thomas

I'm very surprised about your negative appreciation about Twig. Can you tell me more about these points please?

> need to learn something new, twig has maybe less than 20 Php funtions built in ... so took so many time to rewrite everything ....

How long did you spend to learn Twig? What do you mean by rewriting everything?

If you think that having only around 20 PHP built-in functions in Twig is not enough, that means your code doesn't respect MVC. I'm almost sure your code contains lots of business or application logic in your templates. The view layer should just display some data, that's all! So you just need a couple of functions for that.

If your code follows MVC principle, most of the Twig API is enough to generate the view. In some cases, you will have to extend Twig with few Twig extension classes to add new features to the templating engine. But before doing that, try first to refactor your code according MVC principle.

> And Twig is slow... (slower than Smary 3, much slower than Php), if you care about performance, no way to use a template engine!

Do you have metrics to give us?
What is slow?
Do you use APC in production?
Do you use Twig cache to not parse templates everytime and store Twig PHP compiled templates?
Do you load the Twig C extension in your php.ini to boost Twig a little bit?
Which PHP version runs your Twig?

> I am still using it, still reading documentation everytime... nice to lose time ...

If you use an IDE like Eclipse or NetBeans, you have Twig plugins that can help you by providing autocompletion on Twig keywords.

Cheers.

Posted by Thomas - about 1 month ago

Hi Hugo,

If you use APC, means you care about performance like me, really I have a big experience on Smarty and now Twig (with Sf2), even with template caching, the Php generated by Twig is ... just slow ! So there is no sense to use APC and Twig ..

And why Twig ? Smarty did the same thing ! Twig is just a copy of Smarty, but its new, and the web site looks better ... so everyone like it !

I worked in a big project where we need to rewrite almost all Php functions with Twig Extensions (again a performance and time cost).

And the Twig engine is too huge, now I am using a small library I did to simply replace {% by <?php , and other small stuff, here there is a benefit if you care about performance and time.

Leave a comment

Your comment