Custom helpers
Handlebars helpers bring custom PHP logic into templates. The extension's
Helper interface defines a single method:
public function render(\DevTheorem\Handlebars\HelperOptions $options): mixed;
Named arguments passed from the template (e.g., {)
are available as
$options->hash. Positional arguments
(e.g., {) must be declared as additional parameters
in the method signature after
$options:
public function render(HelperOptions $options, ?string $name = null): mixed;
The
Rendering can also be injected by type-hint — declare it
anywhere in the method signature before positional arguments and it is provided
automatically. It gives access to the current PSR-7 request
(
$context->get) and the full set of template variables
(
$context->get):
public function render(HelperOptions $options, ?RenderingContext $context = null): mixed;
The current template scope is accessible via
$options->scope, and block
helpers can call
$options->fn and
$options->inverse to render
their inner blocks.
Implement a helper
Implement the
\CPSIT\ interface and
place the
# attribute on the class. Because the class implements
the
Helper interface, the attribute automatically resolves to the
render
method:
namespace Vendor\Extension\Renderer\Helper;
use CPSIT\Typo3Handlebars\Attribute\AsHelper;
use CPSIT\Typo3Handlebars\Renderer\Helper\Helper;
use DevTheorem\Handlebars\HelperOptions;
#[AsHelper('greet')]
final readonly class GreetHelper implements Helper
{
public function render(HelperOptions $options): mixed
{
return sprintf('Hello, %s!', $options->hash['name'] ?? 'World');
}
}
The attribute can also be placed directly on a method, in which case the method
name is inferred automatically — no
method parameter needed. Dependency
injection works normally for all
#-annotated classes:
use CPSIT\Typo3Handlebars\Attribute\AsHelper;
use CPSIT\Typo3Handlebars\Renderer\Helper\Helper;
use DevTheorem\Handlebars\HelperOptions;
use Vendor\Extension\Domain\Model\Person;
use Vendor\Extension\Domain\Repository\PersonRepository;
#[AsHelper('greet')]
final readonly class GreetHelper implements Helper
{
public function __construct(
private PersonRepository $repository,
) {}
public function render(HelperOptions $options): mixed
{
return sprintf('Hello, %s!', $options->hash['name'] ?? 'World');
}
#[AsHelper('greetAll')]
public function greetAll(HelperOptions $options): mixed
{
return implode(PHP_EOL, array_map(
static fn(Person $person) => sprintf('Hello, %s!', $person->getName()),
$this->repository->findAll(),
));
}
}
Tip
There's no need to implement the
Helper interface, it only serves as a
low-barrier tool to easily get started with custom helper implementations. You
can also just do the following:
use CPSIT\Typo3Handlebars\Attribute\AsHelper;
use DevTheorem\Handlebars\HelperOptions;
#[AsHelper('greet')]
final readonly class GreetHelper
{
public function __invoke(HelperOptions $options): mixed
{
return sprintf('Hello, %s!', $options->hash['name'] ?? 'World');
}
}
Use the helper in a template
Reference the helper by its identifier:
{{greet name="Alice"}}
{{greetAll}}
Alternative: Register via Services.yaml
If you cannot use the attribute (e.g., for a third-party class), register the
helper explicitly in Services.. Both
identifier and
method are required:
services:
Vendor\Extension\Renderer\Helper\GreetHelper:
tags:
- name: handlebars.helper
identifier: 'greetAll'
method: 'greetAll'
See also
Helper interface source on GitHub.