---
title: "Custom helpers"
manual: "Handlebars"
version: "main"
permalink: "https://docs.typo3.org/permalink/cpsit/typo3-handlebars:custom-helpers@main"
source: "Usage/CustomHelpers.rst"
rendered: "2026-09-29T09:05:57+00:00"
---

# Custom helpers {#custom-helpers}

Handlebars helpers bring custom PHP logic into templates. The extension's
`Helper` interface defines a single method:

```php
public function render(\DevTheorem\Handlebars\HelperOptions $options): mixed;
```

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`:

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

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()`):

```php
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](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:implement-a-helper@main)
-   [Use the helper in a template](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:use-the-helper-in-a-template@main)
-   [Alternative: Register via Services.yaml](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:alternative-register-via-file-services-yaml@main)

## Implement a helper {#custom-helpers-implement}

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**

```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');
    }
}
```

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**

```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(),
        ));
    }
}
```

> [!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:
>
> **EXT:my_extension/Classes/Renderer/Helper/GreetHelper.php**
>
> ```php
> 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 {#custom-helpers-use-in-template}

Reference the helper by its identifier:

```handlebars
{{greet name="Alice"}}

{{greetAll}}
```

## Alternative: Register via `Services.yaml` {#custom-helpers-registration-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**

```yaml
services:
  Vendor\Extension\Renderer\Helper\GreetHelper:
    tags:
      - name: handlebars.helper
        identifier: 'greetAll'
        method: 'greetAll'
```

> [!NOTE]
> **See also**
>
> [Helper](https://github.com/CPS-IT/handlebars/blob/main/Classes/Renderer/Helper/Helper.php)
> interface source on GitHub.
