How-to library · Developer docs

How-to library

Task-shaped pages: a title that starts with a verb, the situation in a few lines, the steps, the working code in both engines, and why this way rather than another. Found from a search, done, and left.

Add a filter or extension to a Twig site

You cannot: a theme has no PHP and the platform registers no site extensions. What you can do is a library of macros imported under one name, plus the core filters, the string extension and the platform's own additions.

Context

Context. Stock Twig grows by registering extensions in PHP. A Core dna theme is templates and front-end source only, and the platform's Twig environment takes no extensions from a site, so there is no way to add a filter. What exists instead: the core filters and functions, the string extension (|u for Unicode-safe casing and truncation, |slug), the platform's own additions (debug_vars, the coercion filters, json_decode), the underscore helpers as globals, and macros, which are the way to name a reusable transformation.

Steps

  1. Check whether a core or platform filter already does it: what the platform adds to Twig lists everything registered.
  2. If not, write a macro in a library file, taking the value and any options as arguments and printing the result.
  3. Import the library under a short name wherever it is needed. Underscore variables such as _request and __ are Twig globals, so macros can use them.

Template code

Template code
{* the Smarty equivalent is a template function; one defined in another file is called with call name=excerpt after that file is included *}
{function name=excerpt html='' words=40}{$html|strip_tags|truncate:($words * 7):'…'}{/function}
{excerpt html=$post->body words=30}
{# templates/macros/text.twig #}
{% macro excerpt(html, words = 40) %}
  {%- set plain = html|striptags|u.collapseWhitespace -%}
  {%- set list = plain|split(' ') -%}
  {{- list|slice(0, words)|join(' ') }}{% if list|length > words %}…{% endif -%}
{% endmacro %}

{% macro money(amount, locale = 'en_AU') %}{{ amount.format(locale) }}{% endmacro %}

{# a page template #}
{% import 'macros/text.twig' as text %}
<p>{{ text.excerpt(post.body, 30) }}</p>
<span>{{ text.money(cart.getTotalAsMoney()) }}</span>

Why this and not that

Not a request to the platform team for a custom filter: extensions are global to the platform, not per site. Not logic in JavaScript for what is a rendering concern: it renders empty for crawlers and flashes for visitors. A macro library keeps the rule in one place, which is what a filter was for. Two limits to know: a macro cannot write the caller's variables, and on this platform every set inside it also writes to the shared template context, so give macro-internal names a prefix.

Go deeper

Was this page helpful?

Your answer goes to the docs team.