WordPress is great but working with it can be cumbersome for developers. Twig and Timber are some tools we use to make it easier.
The default templating system is basic PHP template calls that output HTML, giving us complete freedom to do what we want, how we want, with numerous possibilities when it comes to solving any given problem. It’s not perfect by any means but it definitely gets the job done. But there is plenty of room for improvement.
Too much freedom
You can solve any given problem in as many ways as PHP gives you to solve them, this leads to a lack of consistency within projects, templates and even individual files. You can create a single way of doing things within your PHP by creating a style guide but it’s up to individual developers to follow it. An additional, dedicated templating language would make it easier to have a single way of doing things and enforcing your team’s coding system.
Mixing Presentation and Logic
The way WordPress sets up theme templates by default you get a lot of mixed responsibility files. Files that have multiple roles, usually to both get information from the database and then to format that code for display via HTML. This combining of roles leads to complex, difficult to maintain files that have more duplication than necessary.
This doesn’t seem like a big deal until you are working on larger projects where you may have someone who is a specialist WordPress developer who is working on Queries, Fields, data and the CMS itself, alongside a Front End Developer who is crafting the HTML, CSS and the presentation of the page. These people are doing very different work. Separating out their jobs into two independent files allows them to focus better on what they are doing, improves maintainability of the code and helps with reuse as you’ve split the login and the markup into different files.
Easy to introduce security issues
By far, one of the biggest problems with WordPress theme development is just how easy it is to introduce security holes into a theme. It is crucial that developers escape all the output from the server before it is sent to the browser. This sounds simple but it’s easy to forget.
PHP Templating Language for WordPress
Fortunately, these aren’t new problems. These are issues that have been solved in the wider development community and in PHP for many years. A class of library called a “templating language” is used in virtually every major framework and CMS.
Ruby on Rails has Slim and ERB, Django has DTL and Jinja. Javascript has Handlebars, Mustache and Jade. These libraries all do basically the same thing. They let developers separate the logic and presentation layers of code, provide handy shortcuts for common tasks, provide a set of rules that provide consistency, reduce code duplication and prevent some security issues from coming up.
But what about PHP? PHP was originally envisioned as a simple templating language but as its complexity has grown so has the number of templating systems available, a few common options are Blades, Smarty and finally Twig.
Twig and Timber.
WordPress and a templating language won’t work well together by default. You need an intermediary to build the context and the data that the templates need and then passes that to the templating language. In our case, we chose Twig as a templating language out of preference for its syntax and because it is actively maintained by large players in the PHP ecosystem.
Timber is the in-between layer that helps us connect WordPress and Twig along with providing a few extra goodies.
Separating Logic and presentation
Timber and twig let us separate the roles in our files, we contain all the logic we need within the normal template that WordPress loads from a request and then we pass that data to the twig render to combine it with a separate markup file
$projects = new WP_Query([
"post_type" => "project",
"post_status" => "publish",
"posts_per_page" => 6,
]);
if ( $projects->have_posts() ) {
while ( $projects->have_posts() ) {
$projects->the_post();
?>
<div class="tease tease--post">
<?php if(has_post_thumbnail()){ ?>
<a class="tease__image" href="{{item.link}}">
<?php the_post_thumbnail(); ?>
</a>
<?php } ?>
<div class="tease__content">
<h3 class="tease__title type--gamma type--bold">
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</h3>
<p class="tease__text">
<?php the_excerpt(); ?>
</p>
</div>
</div>
<?php
}
}
The original WordPress PHP Template Can be simplified to two files, One getting out data and the Second displaying the template.
$context['projects'] = Timber::get_posts([
"post_type" => "project",
"post_status" => "publish",
"posts_per_page" => 6,
]);
Timber::render( 'project-archive.twig' ), $context );
Our simplified data getting file.
<div class="tease tease--post">
{% if item.thumbnail %}
<a class="tease__image" href="{{item.link}}">
<img src="{{item.thumbnail.src | resize(404, 211) }}" alt="{{item.thumbnail.alt}}" class=""/>
</a>
{% endif %}
<div class="tease__content">
<h3 class="tease__title type--gamma type--bold">
<a href="{{item.link}}">{{item.title}}</a>
</h3>
<p class="tease__text">
{{item.get_preview}}
</p>
</div>
</div>
Our simplified data getting file.
Template Inheritance
We can now reduce the boilerplate code on a template by template basis by using “blocks” in our templates. These named blocks are used to overwrite the same blocks in a template that you are extending.
<div class="template">
<div class="template__main">
{% block content_main %}
{% endblock %}
</div>
<div class="template__sidebar">
{% block content_sidebar %}
Default Sidebar Content
{% endblock %}
</div>
</div>
From out base template we can choose to override any of the blocks in the template. We have no content so we over ride that and we want to use a different sidebar so we override that as well.
{% extends "base.twig "%}
{% block content_main %}
your main content
{% endblock %}
{% block content_sidebar %}
sidebar content
{% endblock %}
Security and Output escaping
All our output is automatically escaped to help prevent common CSRF and XSS attacks. Unless you need something to be explicitly non-escaped.
In Standard PHP, we need to explicitly escape your output
<h4><?php echo esc_html( $title ); ?></h4>
With Twig, the output is automatically escaped.
<h4>{{title}}</h4>
Easier syntax for Front End Developers
Twig reduces the knowledge of PHP that a front-end developer requires to get started and be productive on a project, stripping away a lot of the boilerplate you would otherwise need to remember.
Easier Portability between projects
With Twig (and good development practices) the small components of front-end code you write are not tied to your logic. You can move them between projects easily.
Issues with Twig and Timber
Nothing is completely positive, there will always be a few downsides to anything.
Something extra to learn.
You are adding a new technology to your stack which will slow your team down to start with but can make you much faster in the long term.
Additional Potential Bugs
You are adding a huge new system to WordPress, that gives you so much more room for potential bugs to hide.
It’s not the WordPress way
You are taking a huge divergence from how WordPress actually works. It can be difficult to get a WordPress developer to work on your project. Unless they have some experience of Twig themselves. However, many more PHP developers will feel comfortable in your project.
We love it.
In the end, we love Timber and Twig, we use it all in virtually every project we work with. I encourage you to try it and see just how much more flexible you can make your theme development workflow.