a Sensio Labs Product

The flexible, fast, and secure
template language for PHP

Twig 0.9.5 released

I’m proud to announce the immediate availability of Twig 0.9.5.

Before upgrading from 0.9.4, read this post carefully as this new release might break your existing code.

The documentation has been updated to reflect the changes made in this new version. We have also enhanced the documentation based on the feedback we had.

New Features

.. Operator

One of the main frequently asked question was about iterating over a range of integer. Thanks to the new .. operator, this is now really easy to accomplish:

{% for i in 0..10 %}
  * {{ i }}
{% endfor %}

The above snippet of code prints all numbers from 0 to 9.

The left and right side of the .. operator can be any valid expression:

{% for letter in 'a'..'z' %}
  * {{ letter }}
{% endfor %}

{% for letter in 'a'|upper..'z'|upper %}
  * {{ letter }}
{% endfor %}

Note that the .. operator is just syntactic sugar for the range filter. The first example is equivalent to the following:

{% for i in 0|range(10) %}
  * {{ i }}
{% endfor %}

Array Support

Twig supports a new literal: arrays. Arrays are defined by a sequence of expressions separated by a comma (,) and wrapped with squared brackets ([]). Arrays can also be nested as much as needed:

{% set foo as [a, 'b', ['c', 'd']] %}

Like in PHP, arrays are a mix between lists and dictionaries, arrays and hashes:

{% set foo as ['a': 'a', 'b': 'c'] %}

in Operator

The in operator performs a containment test. It returns true if the left operand is contained in the right one:

{{ 1 in [1, 2, 3] }}
{# returns true #}

{% if current_user in users %}
  {# do something #}
{% endif %}

To perform a negative test, the whole expression should be prefixed with not:

{{ not 1 in [1, 2, 3] }}
{# returns false #}

The in operator is just syntactic sugar for the in filter. The first example is equivalent to the following:

{{ 1|in([1, 2, 3]) }}

Better Filter System

The filter system has been rework to allow for more flexibility. For instance, You can now easily bundle your filters in your extension class:

class Project_Twig_Extension extends Twig_Extension
{
  public function getFilters()
  {
    return array(
      'rot13' => new Twig_Filter_Method($this, 'rot13Filter'),
    );
  }

  public function rot13Filter($string)
  {
    return str_rot13($string);
  }

  public function getName()
  {
    return 'project';
  }
}

include tag

You can now explicitly pass variables when including another template:

{% include 'foo' with ['foo': foo] %}

The with option can be combined with the sandboxed one to allow for very secure templates:

{% include 'foo' sandboxed with vars %}

Speed improvements

This new version of Twig is faster than any other Twig version. The speed gain depends on your templates of course.

For even more speed, you can now disable the automatic creation of the loop variable in a for loop:

{% for i in 0..10 without loop %}
  * {{ i }}
{% endfor %}

Miscellaneous

This version also has many other small improvements. The full changelog read as follows:

  • fixed list nodes that did not extend the Twig_NodeListInterface
  • added the “without loop” option to the for tag (it disables the generation of the loop variable)
  • refactored node transformers to node visitors
  • fixed automatic-escaping for blocks
  • added a way to specify variables to pass to an included template
  • changed the automatic-escaping rules to be more sensible and more configurable in custom filters (the documentation lists all the rules)
  • improved the filter system to allow object methods to be used as filters
  • changed the Array and String loaders to actually make use of the cache mechanism
  • included the default filter function definitions in the extension class files directly (Core, Escaper)
  • added the // operator (like the floor() PHP function)
  • added the .. operator (as a syntactic sugar for the range filter when the step is 1)
  • added the in operator (as a syntactic sugar for the in filter)
  • added the following filters in the Core extension: in, range
  • added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes)
  • enhanced some error messages to provide better feedback in case of parsing errors

Backwards Incompatibilities

Custom Filters

If you have defined custom filters, you MUST upgrade them for this release.

Before 0.9.4, filters were defined with a simple array like this:

// before
'even'   => array('twig_is_even_filter', false),
'escape' => array('twig_escape_filter', true),

As of 0.9.5, a filter is defined as an object and the needs_environment option replaces the Boolean:

// after
'even'   => new Twig_Filter_Function('twig_is_even_filter'),
'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true)),

NodeTransformers

If you have created NodeTransformer classes, you will need to upgrade them to the new interface. Read the built-in transformers classes to learn more about this topic.

Upgrading

Upgrading can be done in a few easy steps:

  • Install the new version (via PEAR, SVN, Git, or by downloading the new package);

  • Read the previous section about backward incompatibilities, and upgrade your code accordingly;

  • Remove all cached templates;

  • Test.

This website is powered by PHP and Twig.