Skip to main content

Context

The template context is the set of variables available in every Twig template. Sloth builds it lazily — values are only resolved when the template actually accesses them.

Built-in context keys

KeyContentCondition
siteSite information — name, url, description, language, …Always
globalsGlobal URLs — home_url, theme_url, images_urlAlways
slothSloth internals — current_layoutAlways
wp_titleCurrent page titleAlways
optionsOptions accessor — {{ options.my_field }}Always
postCurrent post modelSingle posts and pages only
{post_type}Alias for post — e.g. {{ project.title }}Single posts and pages only
taxonomyCurrent taxonomy termTaxonomy archives only
{taxonomy_slug}Alias for taxonomyTaxonomy archives only
authorCurrent authorAuthor archives only
userAlias for authorAuthor archives only

Usage in Twig

{{ site.name }}
{{ site.description }}
{{ globals.theme_url }}
{{ wp_title }}

{# On single posts #}
{{ post.title }}
{{ post.content }}
{{ post.my_acf_field }}

{# On single posts — post type alias #}
{{ project.title }}

{# On taxonomy archives #}
{{ taxonomy.name }}
{{ projectcategory.name }}

{# Options #}
{{ options.primary_color }}
{{ options.blogname }}

Adding custom context

Auto-discovery

Drop a class extending Sloth\Context\ContextProvider into app/Context/ or theme/Context/ and Sloth discovers it automatically:

<?php

namespace App\Context;

use Sloth\Context\ContextProvider;

class NavigationContextProvider extends ContextProvider
{
public function key(): string
{
return 'navigation';
}

public function resolve(): array
{
return [
'primary' => wp_get_nav_menu_items('primary'),
'footer' => wp_get_nav_menu_items('footer'),
];
}
}

Available in Twig immediately:

{% for item in navigation.primary %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% endfor %}

Manual registration

Register a provider in any service provider's boot() method:

public function boot(): void
{
app('context')->register(new MyContextProvider());
}

Conditional providers

Override shouldResolve() to only include the key on certain pages:

class SalesBannerContextProvider extends ContextProvider
{
public function key(): string
{
return 'sales_banner';
}

public function shouldResolve(): bool
{
return is_front_page() || is_shop();
}

public function resolve(): array
{
return [
'text' => options('sales_banner_text'),
'color' => options('sales_banner_color', '#ff0000'),
];
}
}

Static values

For one-off values that don't need a full provider:

app('context')->set('current_step', 3);
app('context')->set('show_sidebar', false);

Provider API

abstract class ContextProvider
{
// The key under which this value is available in Twig
abstract public function key(): string;

// Resolve and return the value — called lazily on first access
abstract public function resolve(): mixed;

// Whether to include this key — defaults to true
public function shouldResolve(): bool
{
return true;
}
}

Context in PHP

// Access a single key (lazy)
app('context')['post'];
app('context')['site'];

// Set a value
app('context')['my_key'] = 'value';
app('context')->set('my_key', 'value');

// Register a provider
app('context')->register(new MyContextProvider());

// Get full context as array (resolves all providers)
app('context')->toArray();

:::tip Production deployment After adding new context providers, run wp sloth manifest:clear to regenerate the manifest cache. See Auto-Discovery. :::

Testing context providers

If your provider calls WordPress functions directly, they may be loaded before Patchwork and cannot be mocked in tests. Wrap them in an injectable class instead:

// app/Context/MyWordPressWrapper.php
class MyWordPressWrapper
{
public function getSomeValue(): string
{
return (string) some_wp_function();
}
}

// app/Context/MyProvider.php
class MyProvider extends ContextProvider
{
public function __construct(
private readonly MyWordPressWrapper $wrapper
) {}

public function key(): string { return 'my_key'; }

public function resolve(): mixed
{
return $this->wrapper->getSomeValue();
}
}

Register via a service provider:

public function boot(): void
{
app('context')->register(
new MyProvider(app(MyWordPressWrapper::class))
);
}

Sloth uses BlogInfo internally for exactly this reason — it wraps get_bloginfo() and home_url() so SiteContextProvider is fully testable. Inject it via app(BlogInfo::class) if you need the same values in your own provider.