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;
Copied!

Named arguments passed from the template (e.g., {{greet name="Alice"}}) are available as $options->hash['name']. Positional arguments (e.g., {{greet "Alice"}}) must be declared as additional parameters in the method signature after $options:

public function render(HelperOptions $options, ?string $name = null): mixed;
Copied!

The RenderingContext 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->getRequest()) and the full set of template variables ( $context->getVariables()):

public function render(HelperOptions $options, ?RenderingContext $context = null): mixed;
Copied!

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\Typo3Handlebars\Renderer\Helper\Helper interface and place the #[AsHelper] attribute on the class. Because the class implements the Helper interface, the attribute automatically resolves to the render method:

EXT:my_extension/Classes/Renderer/Helper/GreetHelper.php
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');
    }
}
Copied!

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 #[AsHelper]-annotated classes:

EXT:my_extension/Classes/Renderer/Helper/GreetHelper.php
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(),
        ));
    }
}
Copied!

Use the helper in a template 

Reference the helper by its identifier:

{{greet name="Alice"}}

{{greetAll}}
Copied!

Alternative: Register via Services.yaml 

If you cannot use the attribute (e.g., for a third-party class), register the helper explicitly in Services.yaml. Both identifier and method are required:

Configuration/Services.yaml
services:
  Vendor\Extension\Renderer\Helper\GreetHelper:
    tags:
      - name: handlebars.helper
        identifier: 'greetAll'
        method: 'greetAll'
Copied!