Skip to main navigation Skip to main content Skip to page footer
TYPO3 v14: Three Fluid 5 Breaking Changes for Integrators

TYPO3 v14: Three Fluid 5 Breaking Changes for Integrators

Have the article read aloud.

Loading the Elevenlabs Text to Speech AudioNative Player...
| TYPO3 | Estimated reading time : min.
This article was automatically translated using DeepL. Therefore, inaccuracies may occur.

Three breaking changes in Fluid 5 affect almost every TYPO3 project: CDATA is no longer removed, variable names with underscore are forbidden and ViewHelpers become more type-safe. The good news - TYPO3 13.4.21 warns you already now.

After the strategic innovations, practical features and asset handling changes in TYPO3 v14, it's time to talk about Fluid 5. TYPO3 v14 comes with the new Fluid version - and it cleans up thoroughly.

Three breaking changes directly affect Fluid templates. The good news: TYPO3 13.4.21 already writes deprecation warnings to the log if your templates are affected. So you can already check now.

1. CDATA sections are no longer removed

What is changing

Previously, Fluid completely removed code in <![CDATA[ ]]> blocks. This was never documented, but many people used it as a workaround to comment out template code.

This no longer works as of Fluid 5. CDATA sections now have a different meaning: they solve an old problem with inline CSS and JavaScript in Fluid templates.

The problem that CDATA now solves

Fluid's syntax with curly braces { } collides with CSS and JavaScript. A media query like @media (min-width: 1000px) { ... } or JavaScript with objects such as const data = {key: value} have previously confused Fluid.

Fluid 5 therefore introduces a new syntax in CDATA blocks:

<f:variable name="color" value="red" />
<style>
<![CDATA[
    @media (min-width: 1000px) {
        p {
            background-color: {{{color}}};
        }
    }
]]>
</style>

The rule: Fluid ignores the normal { } syntax within <![CDATA[ ]]>. Instead, you use three curly braces {{{ }}} for variables and ViewHelpers.

Tag-based ViewHelpers no longer work at all in CDATA blocks - only the inline syntax with three brackets.

What you have to do

If you have used CDATA for commenting out:

Replace <![CDATA[ ]]> with the <f:comment> ViewHelper:

<!-- Alt (no longer works): -->
<![CDATA[
<f:for each="{items}" as="item">
    {item.title}
</f:for>
]]>
<!-- New: -->
<f:comment>
<f:for each="{items}" as="item">
    {item.title}
</f:for>
</f:comment>

The advantage: Since TYPO3 13, <f:comment> also ignores incorrect Fluid syntax. So you can also comment out invalid markup.

If you have inline CSS or JavaScript in templates:

This is still not good practice. But if you can't avoid it, the new CDATA syntax works.

Better: Use data-* attributes, CSS custom properties or dedicated API endpoints to pass dynamic values to CSS and JavaScript.

Affected projects

Since TYPO3 13.4.21 Fluid writes a deprecation to the log if it finds <![CDATA[ ]]> to comment out. Check your deprecation log before migrating to v14.

2. variable names with underscore prefix are forbidden

What changes

Fluid 5 reserves all variable names starting with an underscore for internal purposes. This is similar to {_all}, which has existed for some time.

These examples no longer work:

<f:variable name="_temp" value="a temporary value" />
{_temp}
<f:for each="{myArray}" as="_item">
    {_item}
</f:for>
<f:render partial="Footer" arguments="{_data: myData}" />

Also in PHP code:

$view->assign('_data', $myData);
$view->assignMultiple([
    '_data' => $myData,
]);

All these cases throw an exception as of Fluid 5:

#1756622558 TYPO3Fluid\\Fluid\\Core\\Variables\\InvalidVariableIdentifierException
Variable identifiers cannot start with a "_": _myVariable

What is NOT affected

Property names and array keys still work with underscore:

{myArray._myKey}
{myObject._myProperty}

Internal variables such as {_all} are retained:

<f:render partial="Footer" arguments="{_all}"/>

Migration

Simple: Rename the variables. Instead of _temp use temp, instead of _item use item.

Since TYPO3 13.4.21 Fluid also writes a deprecation in the log if affected variable names are found.

3. strict typing in ViewHelpers

Fluid 5 becomes stricter with types. This affects three areas:

3.1 Stricter validation of ViewHelper arguments.

Until now, Fluid had many blind spots when it came to argument validation. ViewHelpers could not trust that the types they defined in their API were correct.

Now Fluid validates more strictly. Arguments that previously passed as "valid" (but did not match the ViewHelper API) are now rejected.

Good news: Fluid automatically converts simple types. A ViewHelper that expects a string also accepts an int.

For integrators: Some ViewHelper calls that worked before might now fail - but these were mostly bugs in the template code anyway.

For extension developers: You can now rely on the argument types and remove custom validation logic.

3.2 null values in tag-based ViewHelpers

Previously, Fluid's TagBuilder treated null values as empty strings. This resulted in HTML attributes with an empty value:

<f:form.textfield name="myTextBox" placeholder="{variableThatMightBeNull}" />

Fluid 4 and earlier:

<input type="text" name="myTextBox" placeholder="" />

Fluid 5:

<input type="text" name="myTextBox" />

The attribute is completely omitted.

Affected ViewHelpers in the TYPO3 core:

  • <f:media> and <f:image>
  • <f:asset.css> and <f:asset.script>
  • <f:form> and <f:form.*>
  • <f:link.*> (except <f:link.typolink>, which uses TypoScript)
  • <f:[be.link](<http://be.link>)>
  • <be:link.*>
  • <be:thumbnail>

Practical impact: In most cases irrelevant. But with some ViewHelpers (e.g. <f:image>) the core had to be adapted to always render the alt attribute - even if the value is zero.

3.3 Return type declarations in ViewHelper classes

Fluid's ViewHelperInterface now requires explicit return types for all methods.

If you develop your own ViewHelpers, you must adapt them:

class MyViewHelper extends AbstractViewHelper
{
    // render() should specify a return type (not void)
    public function render(): string
    {
        return 'Hello World';
    }
    // initializeArguments() needs void
    public function initializeArguments(): void
    {
        $this->registerArgument('name', 'string', 'The name');
    }
}

Properties are NOT affected:

class MyViewHelper extends AbstractViewHelper
{
    protected $escapeOutput = false; // No type declaration necessary
    protected $escapeChildren = false;
}

This change is backwards compatible. So you can already customize your extensions now, and they will work with TYPO3 13 and earlier.

Automatic testing difficult

Unfortunately, most of these changes cannot be scanned automatically. They depend on specific variable values that are passed to templates at runtime.

On the plus side, most of the problems that Fluid 5 uncovers were previously bugs - for example, when an array was passed to a ViewHelper that expects a string.

The strategy behind it

Fluid 5 clears up technical debts:

  • Documented syntax instead of workarounds: CDATA gets an official function instead of being abused as a hack
  • Clearer namespaces: Underscore prefix for internal variables so that future Fluid versions do not create conflicts
  • Type safety: ViewHelpers can rely on their API, less defensive programming required

This fits into the picture of TYPO3 v14: less legacy, clearer structures, modern standards.

How to prepare yourself

Already testable:

Since TYPO3 13.4.21, Fluid Deprecations writes to the log if your templates are affected by the first two breaking changes:

  • CDATA for commenting out
  • Variable names with underscore prefix

Check your deprecation log before migrating to v14.

Extension Scanner for Custom ViewHelper:

The Extension Scanner finds ViewHelpers without return type declarations. If you develop your own extensions, run it.

Runtime tests:

The other changes (argument validation, null handling) depend on runtime values. Automatic scanning is not possible. Test your templates thoroughly after the upgrade.

How to stay informed

TYPO3 v14 is still under development. I continue to filter the relevant changes from the ChangeLog and present them here in the blog.

If you want to receive updates directly, subscribe to my TYPO3 newsletter. There you will get the most important developments in a compact format - without noise, only what is really relevant.

There will of course be another comprehensive video course on TYPO3 v14 - as soon as the version is closer to release.

Sources & links

All code examples in this article are taken directly from the official TYPO3 ChangeLog and have been adopted unchanged.

Breaking #108148 - CDATA Sections In Fluid Templates No Longer Removed

Feature #108148 - Alternative Fluid Syntax for CDATA Sections

Breaking #108148 - Disallow Fluid Variable Names With Underscore Prefix

Breaking #108148 - Strict Types in Fluid ViewHelpers

Back

Who writes here?

Hi, I am Wolfgang.

Since 2006, I've been diving deep into the fascinating world of TYPO3 - it's not only my profession, but also my passion. My path has taken me through countless projects, and I have created hundreds of professional video tutorials focusing on TYPO3 and its extensions. I love unraveling complex topics and turning them into easy-to-understand concepts, which is also reflected in my trainings and seminars.

As an active member of the TYPO3 Education Committee, I am committed to keeping the TYPO3 CMS Certified Integrator exam questions current and challenging. Since January 2024, I am proud to be an official TYPO3 Consultant Partner!

But my passion doesn't end at the screen. When I'm not diving into the depths of TYPO3, you'll often find me on my bike, exploring the picturesque trails around Lake Constance. These outdoor excursions are my perfect balance - they keep my mind fresh and always provide me with new ideas.