Building a Custom Twig Filter the TDD Way

An excerpt from, by Taylor Ren

Twig is a powerful, yet easy to master template engine. It is also my personal favorite as all my web development is based on either Symfony or Silex.

Apart from its core syntax ({{ ... }} and {% ... %}), Twig has built-in support for various filters. A filter is like a “converter”. It receives certain original data (a string, a number, a date, etc) and by applying a conversion, outputs the data in a new form (as a string, a number, a date, etc). For example, the number_format filter can convert a number into a more readable one:

{{price|number_format(2, '.', ',')}}

Assuming price is a variable with value 1234567.12345, after the filter operation, the output in the page will be 1,234,567.12: 2 decimal places, “.” as the decimal point and “,” as the thousands separator. This makes it much more readable.

As another example, capitalize will make every first letter of a word in a sentence uppercase and others lowercase:


Assuming title is a variable with the value this tutorial is nice, after the filter operation, the output will be This Tutorial Is Nice.

Twig has a number of built-in filters. The full list can be found in its official documentation.

Why Choose a Filter?

Some may argue that the above functionality is also doable in PHP; that is true. We also often find the functionality provided by built-in filters quite limited and insufficient. So, why use a filter?

In an MVC environment, the model layer is responsible for providing data (a book price or an article title, for example). The view layer is responsible for displaying the data. Doing the data conversion, filter-style, in a controller is not advisable because it is against the design role of a controller, and doing it in a model effectively changes the data, which is not good. In my opinion, the view is the only viable option.

Besides, as a particular transformation of data may be requested in many places in a template (as well as in various templates) on the same data from various sources, it is better to call that filter in the template every time such a conversion is required, than to call a function in the controller. The code will be much tidier.

Let’s consider the following code segments comparing using a filter and a PHP function call (using Symfony 2 + Doctrine). We can easily see the differences in elegance and usability.

Filter version:

<em>{{ book.title|capitalize }}</em> has {{book.pages|number_format(2, ".", ",")}}
and costs ${{ book.price|number_format(2, ".", ",")}}.  

And for this approach, what we do in the controller will be:

return $this->render('A_Template', ['book'=>$book]);

Find the book (the data) and pass it to the view to display.

But if we use PHP function calls, the code may look like this:

//Using PHP function within a Symfony framework and Doctrine
$book['tmpTitle'] = ucwords($book->getTitle);
$book['tmpPage'] = number_format($book->getPages(), 2, ".", ",");
$book['tmpPrice'] = number_format($book->getPrice(), 2, ".", ",");
return $this->render('A_Template', ['book'=>$book]);

… and then in the template

<em>{{ book.tmpTitle }}</em> has {{book.tmpPages}}
and costs ${{ book.tmpPrice}}.

You can see that the filter approach is much cleaner and easier to manage, with no clumsy temp variables in between.

Continue reading this article on SitePoint!

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.