Skip to main content

Expressions & Syntax

This page is the full reference for Unblock's expression syntax — operators, filters, literals, and functions.

Unblock uses Twig expression syntax. Based on Twig and Timber, this syntax is widely used and well-documented.

The Basics

These patterns cover 90% of real-world usage.

Accessing Data

Use dot notation to access properties:

{{ post.title }}
{{ post.author.name }}
{{ site.name }}

Bracket Notation

Access array elements or dynamic properties:

{{ array[0] }}
{{ array['key'] }}
{{ post.meta('field_name') }}

Optional Chaining

Safely access properties that might be null:

{{ post.author?.name }}
{{ post.thumbnail?.src }}

Method Calls

Call methods with arguments:

{{ post.date('F j, Y') }}
{{ post.excerpt({words: 25}) }}
{{ user.avatar(96) }}
{{ post.meta('price') }}

Function Calls

Call built-in functions directly in expressions:

{{ min(1, 2, 3) }}
{{ max(prices) }}
{{ random() }}
{{ range(1, 10) }}
{{ html_classes('btn', {active: is_active}) }}

WordPress functions return provider objects, so you can chain property access:

{{ get_post(42).title }}
{{ get_term(5).name }}
{{ get_image(thumbnail_id).src('medium') }}
{{ get_posts({post_type: 'page', posts_per_page: 5}) }}

See Functions for the complete list.

Filters

Transform values using the pipe (|) operator:

{{ value|filter }}
{{ value|filter(argument) }}
{{ value|filter(arg1, arg2) }}

Chaining Filters

Apply multiple filters in sequence:

{{ post.title|lower|slug }}
{{ post.content|striptags|truncate(150) }}
{{ post.date|date_modify('+1 day')|date('F j, Y') }}

See Filters for the complete list.

Conditional Logic

Ternary Operator

{{ condition ? 'yes' : 'no' }}
{{ post.thumbnail ? 'Has image' : 'No image' }}
{{ user.logged_in ? user.name : 'Guest' }}

Short syntax (returns empty if false):

{{ user.logged_in ? 'Welcome!' }}

Fallback Operators

OperatorNameReturns fallback whenExample
??Null coalescingValue is null{{ post.subtitle ?? 'No subtitle' }}
?:Elvis (falsy coalescing)Value is falsy (null, false, 0, '', []){{ post.views ?: 0 }}
{{ post.subtitle ?? 'No subtitle' }}
{{ post.image ?? post.thumbnail ?? '/default.jpg' }}
{{ post.views ?: 0 }}

Comparison: ?? vs ?: vs |default

Value?? returns?: returns|default returns
'text''text''text''text'
nullfallbackfallbackfallback
falsefalsefallbackfallback
00fallback0
''''fallbackfallback
[][]fallbackfallback
  • ?? — returns fallback only when null. Preserves false, 0, '', [].
  • ?: — returns fallback when falsy (null, false, 0, '', []).
  • |default — returns fallback when empty (like ?: but preserves 0).

Text Operations

Concatenation

Use + or ~ to concatenate strings:

{{ 'Hello, ' + user.name + '!' }}
{{ post.title + ' - ' + site.name }}
{{ 'Hello ' ~ user.name }}

Note: + auto-detects: it concatenates when either side is a string, otherwise it adds numbers. ~ always concatenates by casting both sides to strings.

Testing Strings

{{ post.title starts with 'Hello' }}
{{ post.slug ends with '-draft' }}

Containment

{{ 'a' in ['a', 'b'] }}
{{ 'c' not in ['a', 'b'] }}
{{ post.status in ['publish', 'future'] }}

Operators

Arithmetic

OperatorDescriptionExample
+Addition / Concatenation{{ 5 + 3 }}8
-Subtraction{{ 10 - 3 }}7
*Multiplication{{ 4 * 5 }}20
/Division{{ 20 / 4 }}5
%Modulo{{ 17 % 5 }}2
//Floor division{{ 17 // 5 }}3
**Power{{ 2 ** 3 }}8
..Range{{ 1..5 }}[1, 2, 3, 4, 5]

Comparison

OperatorDescriptionExample
==Equal{{ a == b }}
!=Not equal{{ a != b }}
===Identical{{ a === b }}
!==Not identical{{ a !== b }}
<Less than{{ a < b }}
>Greater than{{ a > b }}
<=Less or equal{{ a <= b }}
>=Greater or equal{{ a >= b }}
<=>Spaceship{{ a <=> b }}

Logical

OperatorDescriptionExample
andLogical AND{{ a and b }}
orLogical OR{{ a or b }}
notLogical NOT{{ not a }}

String

OperatorDescriptionExample
~Concatenation{{ 'Hello ' ~ name }}
starts withStarts with test{{ post.title starts with 'Hello' }}
ends withEnds with test{{ post.slug ends with '-draft' }}

Containment

OperatorDescriptionExample
inContains{{ 'a' in ['a', 'b'] }}
not inNot contains{{ 'c' not in ['a', 'b'] }}

Operator Precedence

From lowest to highest priority:

  1. ? — Ternary
  2. or — Logical OR
  3. ??, ?: — Fallback
  4. and — Logical AND
  5. | — Filter
  6. ==, !=, ===, !==, <, >, <=, >=, <=>, in, not in, starts with, ends with — Comparison
  7. .. — Range
  8. +, -, ~ — Addition / Concatenation
  9. *, /, %, // — Multiplication / Division
  10. ** — Power (right-associative)
  11. not — Logical NOT

Use parentheses to control evaluation order:

{{ (a + b) * c }}
{{ (value ?? 'default')|upper }}
{{ (post.views ?: 0) + 1 }}

Literals

Strings

{{ 'single quotes' }}
{{ "double quotes" }}

Numbers

{{ 42 }}
{{ 3.14 }}
{{ -10 }}

Booleans

{{ true }}
{{ false }}

Null

{{ null }}

Arrays

{{ [1, 2, 3] }}
{{ ['a', 'b', 'c'] }}

Objects

{{ {key: 'value'} }}
{{ {name: 'John', age: 30} }}

Variables

Use the Variable block to store and reuse values. Create a variable with a name and an expression, then reference it anywhere in child blocks:

{{ my_price|number_format(2) }}
{{ display_title }}

See Variables for full documentation.

Arrow Functions

Used with higher-order filters like map, filter, sort, reduce, and find:

Single Parameter

{{ items|map(p => p.name) }}
{{ items|filter(p => p.active) }}
{{ items|find(p => p.id == 5) }}
{{ items|sort(p => p.date) }}

Multiple Parameters

{{ items|sort((a, b) => a.date <=> b.date) }}
{{ items|reduce((carry, item) => carry + item.price, 0) }}

Complex Expressions

{{ posts|filter(p => p.status == 'publish' and p.author.id == user.id) }}
{{ products|map(p => p.price * 1.2) }}

See Array Filters for all available higher-order filters.

Escaping & Output

Auto-Escaping

All output is automatically escaped — you never need to think about it. UnBlock combines two layers of protection:

  • Field-aware: each field knows its type. Text fields use esc_html, URL fields like post.link use esc_url, and HTML fields like post.content are already processed by WordPress.
  • Context-aware: expressions in HTML attributes are escaped with esc_attr (or esc_url for URL attributes like href and src), regardless of the field used.
{{ post.title }}                <!-- esc_html in text, esc_attr in attributes -->
{{ post.link }} <!-- esc_url everywhere -->
{{ post.content }} <!-- Pre-processed HTML, safe to output -->

Comments

Comments are not rendered in the output:

{# This is a comment #}

Reserved Keywords

The following cannot be used as variable names:

  • true, false
  • null, none
  • and, or, not
  • in
  • if, else

Error Handling

Missing Properties

Missing properties return an empty string — no errors:

{{ post.nonexistent }}  <!-- Returns '' -->

Safe Navigation

Properties are safely navigated — no errors on null:

{{ post.author.name }}  <!-- Safe even if author is null -->

Default Values

{{ value|default('fallback') }}
{{ value ?? 'fallback' }}