PathProvider & VariableProvider 

Two further interfaces allow contributing template paths and global variables from PHP rather than from TypoScript or Services.yaml configuration. Both are auto-registered via #[AutoconfigureTag] and both use a priority integer to control merge order, set via Symfony's #[AsTaggedItem(priority: ...)] attribute on the implementing class.

PathProvider 

Implement the \CPSIT\Typo3Handlebars\Renderer\Template\Path\PathProvider interface to contribute template and partial root paths programmatically — for example when paths depend on the current site configuration or a value not available at container compile time.

Higher priority values are merged last and therefore take precedence over lower ones. The three built-in providers use 0 ( GlobalPathProvider ), 50 ( TypoScriptPathProvider ), and 100 ( ContentObjectPathProvider ).

interface PathProvider
Fully qualified name
\CPSIT\Typo3Handlebars\Renderer\Template\Path\PathProvider
getTemplateRootPaths()

Return an array of template root paths, keyed by integer priority.

returntype

array

getPartialRootPaths()

Return an array of partial root paths, keyed by integer priority.

returntype

array

isCacheable()

Return true if the paths provided by this provider may be cached. Return false for request-dependent paths.

returntype

bool

EXT:my_extension/Classes/Renderer/Template/Path/SitePathProvider.php
namespace Vendor\Extension\Renderer\Template\Path;

use CPSIT\Typo3Handlebars\Renderer\Template\Path\PathProvider;
use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
use TYPO3\CMS\Core\Site\SiteFinder;

#[AsTaggedItem(priority: 25)]
final readonly class SitePathProvider implements PathProvider
{
    public function __construct(
        private SiteFinder $siteFinder,
    ) {}

    public function getTemplateRootPaths(): array
    {
        return [];
    }

    public function getPartialRootPaths(): array
    {
        return [];
    }

    public function isCacheable(): bool
    {
        return false;
    }
}
Copied!

The class is picked up automatically because PathProvider carries #[AutoconfigureTag('handlebars.template_path_provider')] . No extra Services.yaml entry is needed beyond standard autowiring. The #[AsTaggedItem(priority: ...)] attribute on the class determines merge order; without it, the provider defaults to priority 0.

VariableProvider 

Implement the \CPSIT\Typo3Handlebars\Renderer\Variables\VariableProvider interface to inject variables into every template rendering without repeating them in TypoScript. Common uses include a site-wide locale string, feature flags, or shared navigation data.

Providers are merged in ascending priority order; a higher-priority provider can overwrite keys from a lower-priority one. The built-in GlobalVariableProvider uses priority 0.

interface VariableProvider
Fully qualified name
\CPSIT\Typo3Handlebars\Renderer\Variables\VariableProvider
get()

Return the variables contributed by this provider.

returntype

array

isCacheable()

Return true if the variables provided by this provider may be cached. Return false for request-dependent variables. If any registered provider returns false , the merged VariableBag result is not cached and is recomputed on every access.

returntype

bool

EXT:my_extension/Classes/Renderer/Variables/SiteVariableProvider.php
namespace Vendor\Extension\Renderer\Variables;

use CPSIT\Typo3Handlebars\Renderer\Variables\VariableProvider;
use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
use TYPO3\CMS\Core\Site\SiteFinder;

#[AsTaggedItem(priority: 10)]
final readonly class SiteVariableProvider implements VariableProvider
{
    public function __construct(
        private SiteFinder $siteFinder,
    ) {}

    public function get(): array
    {
        return [
            'siteName' => $this->siteFinder->getSiteByPageId(0)->getIdentifier(),
        ];
    }

    public function isCacheable(): bool
    {
        return true;
    }

    public function offsetExists(mixed $offset): bool
    {
        return array_key_exists($offset, $this->get());
    }

    public function offsetGet(mixed $offset): mixed
    {
        return $this->get()[$offset] ?? null;
    }

    public function offsetSet(mixed $offset, mixed $value): never
    {
        throw new \LogicException('Variables are read-only.', 1781693633);
    }

    public function offsetUnset(mixed $offset): never
    {
        throw new \LogicException('Variables are read-only.', 1781693639);
    }
}
Copied!

Like PathProvider , the class is picked up automatically via #[AutoconfigureTag('handlebars.variable_provider')] on the interface. The #[AsTaggedItem(priority: ...)] attribute on the class determines merge order; without it, the provider defaults to priority 0.