Migration 

This page lists required migration steps when upgrading to a new major version of the extension.

Version 1.0.0 

Version 1.0.0 replaces the previous PHP-class rendering model (DataProcessor / DataProvider / Presenter) with the HANDLEBARSTEMPLATE content object. All rendering configuration moves to TypoScript; custom PHP classes are no longer the entry point.

Removed classes and interfaces 

The following classes and interfaces have been removed and have no replacement:

  • \CPSIT\Typo3Handlebars\DataProcessing\DataProcessor (interface)
  • \CPSIT\Typo3Handlebars\DataProcessing\AbstractDataProcessor
  • \CPSIT\Typo3Handlebars\Data\DataProvider (interface)
  • \CPSIT\Typo3Handlebars\Data\Response\ProviderResponse (interface)
  • \CPSIT\Typo3Handlebars\Presenter\Presenter (interface)
  • \CPSIT\Typo3Handlebars\Presenter\AbstractPresenter
  • \CPSIT\Typo3Handlebars\DataProcessing\SimpleProcessor

The handlebars.processor service tag has also been removed.

TypoScript entry point 

Before: Each content element was routed to a DataProcessor class via a USER content object:

tt_content.header = USER
tt_content.header.userFunc = Vendor\Extension\DataProcessing\HeaderProcessor->process
Copied!

After: Use HANDLEBARSTEMPLATE directly:

tt_content.header = HANDLEBARSTEMPLATE
tt_content.header {
    templateName = Header

    variables {
        header = TEXT
        header.field = header

        subheader = TEXT
        subheader.field = subheader
    }
}
Copied!

Data preparation (DataProvider → variables / dataProcessing) 

Before: Data was prepared in a DataProvider class and returned as a ProviderResponse object, which the Presenter then passed to the renderer.

After: Data is prepared entirely in TypoScript:

  • Simple field values: use variables with content objects such as TEXT, FILES, etc.
  • Database relations and menus: use standard TYPO3 dataProcessing processors (e.g., database-query, menu).
  • Per-record variable processing inside a loop: use process-variables.

Template selection (Presenter → templateName) 

Before: The Presenter called $this->renderer->render('path/to/template', $data).

After: The template is declared in TypoScript:

tt_content.my_element {
    templateName = MyElement
}
Copied!

For conditional template selection, use stdWrap on templateName:

tt_content.my_element {
    templateName = MyElement
    templateName.override.if {
        isTrue.field = tx_myext_variant
        value = special
    }
    templateName.override = MyElementSpecial
}
Copied!

Helper registration 

Before: Helpers were registered via Services.yaml tags:

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

After: Use the #[AsHelper] attribute directly on the class or method:

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

The Services.yaml tag approach still works and can be used if you cannot modify the helper class (e.g., a third-party class).

Debug mode 

The debug mode built into HandlebarsRenderer has been removed. Previously, when TYPO3's config.debug flag or $GLOBALS['TYPO3_CONF_VARS']['FE']['debug'] was enabled, the renderer automatically bypassed the template cache and switched the Handlebars compiler to strict mode (throwing on missing variables instead of silently returning empty strings).

There is no automatic replacement tied to a debug flag. Use the following alternatives instead:

  • Cache bypass: Disable caching explicitly via TYPO3's caching framework configuration or by setting config.no_cache = 1 during development.
  • Strict compilation: Enable rendering.strictMode in the extension configuration. Unlike the previous behavior, this is a persistent setting rather than one tied to TYPO3's debug flags.
  • Strict template validation: Use the shipped {{debug}} helper inside templates to inspect variable values at render time. For programmatic checks, call Handlebars::precompile() directly to inspect the generated PHP code.

Template path configuration 

Template path configuration via Services.yaml and TypoScript remains unchanged. In addition, paths can now also be set per-content-object directly in HANDLEBARSTEMPLATE:

tt_content.textmedia = HANDLEBARSTEMPLATE
tt_content.textmedia {
    templateRootPaths.10 = EXT:my_extension/Resources/Private/Templates
    partialRootPaths.10 = EXT:my_extension/Resources/Private/Partials
}
Copied!