TemplateResolver
Implement the \CPSIT\Typo3Handlebars\Renderer\Template\TemplateResolver interface to change how template and partial names are resolved to absolute file paths — for example to support a different directory layout, an additional file extension, or a database-driven path lookup.
The extension ships two implementations:
\CPSIT\ (the
default) and
\CPSIT\.
\CPSIT\ implements
supports and provides protected helpers for normalizing root paths and
resolving filenames with
EXT: syntax. Extending it keeps
implementations concise.
- interface TemplateResolver
-
- Fully qualified name
-
\CPSIT\
Typo3Handlebars\ Renderer\ Template\ Template Resolver
- supports ( string $fileExtension)
-
Return
trueif this resolver handles the given file extension.- param string $fileExtension
-
File extension without leading dot.
- returntype
-
bool
FlatTemplateResolver
Flat is the default implementation. It scans all
configured root paths recursively and builds an in-memory map of every
template file, keyed by its bare filename (without directory). A lookup
therefore succeeds regardless of where in the directory tree the file lives.
Template and partial names must be prefixed with @ to trigger flat
resolution. A name without the prefix is passed directly to
Handlebars (see below).
tt_content.tx_myext_teaser = HANDLEBARSTEMPLATE
tt_content.tx_myext_teaser {
templateName = @teaser
}
{{> @card}}
Variant separator
Appending --<variant> to an @-prefixed name selects a variant
of a component. If no file with that exact name exists, the resolver automatically
falls back to the base name:
{{> @card--highlighted}} {{!-- falls back to @card if not found --}}
This convention follows Fractal's naming rules.
File precedence
When the same filename exists under multiple root paths, the higher-priority root path wins (see Template paths). Within a single root path, files are sorted by name and the first occurrence is used, matching Fractal's uniqueness guarantee.
HandlebarsTemplateResolver
Handlebars resolves template and partial names as
paths relative to the configured root paths. Given the name Blog/,
it searches each root path (highest priority first) for a matching file —
for example Blog/.
This resolver is used as the fallback inside
Flat
for any name that does not start with @, so both resolution strategies
are active at the same time.
Example implementation
namespace Vendor\Extension\Renderer\Template;
use CPSIT\Typo3Handlebars\Exception;
use CPSIT\Typo3Handlebars\Renderer\Template\BaseTemplateResolver;
use CPSIT\Typo3Handlebars\Renderer\Template\TemplatePaths;
final readonly class MyTemplateResolver extends BaseTemplateResolver
{
public function __construct(
private TemplatePaths $templatePaths,
) {}
public function resolveTemplatePath(string $templatePath, ?string $format = null): string
{
[$templateRootPaths] = $this->resolveTemplatePaths($this->templatePaths);
foreach (array_reverse($templateRootPaths) as $rootPath) {
$filename = $this->resolveFilename($templatePath, $rootPath, $format ?? 'hbs');
if (is_file($filename)) {
return $filename;
}
}
throw new Exception\TemplatePathIsNotResolvable($templatePath);
}
public function resolvePartialPath(string $partialPath, ?string $format = null): string
{
[, $partialRootPaths] = $this->resolveTemplatePaths($this->templatePaths);
foreach (array_reverse($partialRootPaths) as $rootPath) {
$filename = $this->resolveFilename($partialPath, $rootPath, $format ?? 'hbs');
if (is_file($filename)) {
return $filename;
}
}
throw new Exception\PartialPathIsNotResolvable($partialPath);
}
}
Wiring the implementation
Register the custom resolver as the implementation of the
Template interface in your extension's Services.:
services:
CPSIT\Typo3Handlebars\Renderer\Template\TemplateResolver:
alias: Vendor\Extension\Renderer\Template\MyTemplateResolver