First impressions of Twig

I was excited to learn that my first project at Torchbox would be a Drupal project… but with a twist.

As Ru explained in an earlier blog post, the project I would be working on was to be a headless Drupal build, using Silex for the front-end, and templating with Twig rather than with Drupal’s own theming system. This presented a challenge but also an opportunity to expand my horizons and experience working in a different way than I was used to.

I’d heard only good things about Twig from friends in the development community, and together with its adoption into Drupal 8, I was looking forward to getting stuck in.

It didn’t take long to get my head around the two basic types of delimiter; evaluation tags {% … %} which are used to set variables, test conditions, loop through arrays, and output tags {{ … }} which are used for translating values into strings. Using each type of tag where needed allows Twig to flexibly accommodate almost any markup structure that you could wish for. With this knowledge, and the theory behind one of Twig’s most powerful features, template inheritance, I was free to begin moulding the structure of the site to do what we needed it to.

For our project, we chose to work outwards from a base template containing all the blocks needed for the site. A block simply represents a region: a chunk of code contained within {% block [name] %} … {% endblock %} tags. You are not compelled to work in this way, but it worked well for us.

The majority of the project’s templates inherit their markup structure from the aforementioned base, and will typically alter it by overriding one or more blocks. For example, the site’s user dashboard, which contains relevant content from the site based on the information we have about them, overrides the content block with its own dashboard-related content. Listed on the dashboard are groups of articles called collections, which users of the site can create and populate if they wish to. Wherever we need to display a list of a user’s collections, we simply include the collection template, passing it an array of values it needs to display. This clever inheritance system cuts down greatly on code duplication and speeds up development.

Earlier I mentioned Twig’s evaluation tags, between which you can use test conditions and loop through arrays, among other things. Twig also provides themers with filters, which are kind of like encapsulated functions. They perform operations on a given value or series of values, providing you with a great deal of flexibility. From relatively simple usages, such as capitalising the first letter of a sentence (|capitalize), through to more complex operations such as merging two arrays together (|merge) or batching together groups of items within an array for output (|batch), Twig’s filters are so useful and can save so much time. Check out the full list at Twig’s documentation.

At first, it didn’t sit quite right with me to be including “logic” in the template files, especially as naturally and liberally as you can with Twig. Surely this couldn’t be right given the amount of times I’d had it drilled into me that logic does not belong in template files. But why would these brilliant, useful tools even be a part of Twig if they weren’t supposed to be used? I happened to mention this to another developer on the project, who went on to say something very wise, something I hadn’t even considered before. He made the distinction between “business” logic (for want of a better word), and “theming” logic. Theming logic, relating purely to layout and the display of data, is perfectly allowed in your templates, so join me in making full use of Twig’s built in functions and filters and don’t ever feel bad about it.

As I spend more time using Twig, I’m continually learning about new conveniences that Twig provides the themer. On one occasion I needed something to happen on the first iteration of a loop. Simple enough, right? Yes, but not the way I was doing it. I was testing on the key of the array, which is not ideal since it requires the keys to be both numeric and sequential, which mine weren’t. No longer than five seconds after I was through making the necessary changes to my array, a colleague sent through an article entitled ‘Where am I in the Twig Loop?’ which outlines several dedicated loop variables provided by Twig – the exact solution to my problem! I could simply test on loop.first, and so I did there and then.

All of this is not to say that there haven’t been any bumps in the road using Twig for our project, but I am inclined to think that many, if not all, of them could be smoothed out on future projects. Take as a case in point the bloating of our templates directory. Having as we did no meaningful structure to the files living in said directory, nor any agreed-upon convention for file names, it was difficult to locate the correct file at times. This is something which could be rectified with a little forethought and some kind of plan.

Overall, I have been very impressed with Twig. After spending the best part of my career so far working with Drupal’s theming system, which certainly has its own strengths, it was a pleasure to work with a tool that hands over so much of the responsibility over to you. Rather than overriding existing templates, there will be nothing in your site’s markup that you didn’t put there. Twig is a mature and robust templating language that I would not hesitate to recommend using it on a future project.