Migration from Latte 3.0

Latte 3.1 brings several improvements and changes that make templates safer and more convenient to write. Most changes are backward compatible, but some require attention during migration. This guide summarizes the breaking changes and how to handle them.

Latte 3.1 requires PHP 8.2 or newer.

Smart Attributes and Migration

The most significant change in Latte 3.1 is the new behavior of Smart Attributes. This affects how null values and boolean values in data- attributes are rendered.

  1. null values: Previously, title={$null} rendered as title="". Now, the attribute is completely dropped.
  2. data- attributes: Previously, data-foo={=true} / data-foo={=false} rendered as data-foo="1" / data-foo="". Now, it renders as data-foo="true" / data-foo="false".

To help you identify places where the output has changed in your application, Latte provides a migration tool.

Migration Warnings

You can enable migration warnings, which will warn you during rendering if the output differs from Latte 3.0.

$latte = new Latte\Engine;
$latte->setMigrationWarnings();

When enabled, check your application logs or Tracy bar for E_USER_WARNINGs. Each warning will point to the specific line, and column in template.

How to resolve warnings:

If the new behavior is correct (e.g. you want the empty attribute to disappear), confirm it using the |accept filter to suppress the warning:

<div class="{$var|accept}"></div>

If you want to keep the attribute as empty (e.g. title="") instead of dropping it, use the null coalescing operator:

<div title={$var ?? ''}></div>

Or, if you strictly require the old behavior (e.g. "1" for true), explicitly cast the value to string:

<div data-foo={(string) $bool}></div>

After you resolve all warnings:

Once all warnings are resolved, disable migration warnings and remove all |accept filters from your templates, as they are no longer needed.

Strict Types

Latte 3.1 enables declare(strict_types=1) by default for all compiled templates. This improves type safety but might cause type errors in PHP expressions inside your templates if you were relying on loose typing.

If you cannot fix the types immediately, you can disable this behavior:

$latte->setStrictTypes(false);

Global Constants

The template parser has been improved to better distinguish between simple strings and constants. As a result, global constants must now be prefixed with a backslash \.

{* Old way (throws a warning; in the future will be interpreted as the string 'PHP_VERSION') *}
{if PHP_VERSION > ...}

{* New way (correctly interpreted as constant) *}
{if \PHP_VERSION > ...}

This change prevents ambiguity and allows you to use unquoted strings more freely.

Removed Features

Reserved Variables: Variables starting with $__ (double underscore) and the variable $this are now strictly reserved for Latte's internal use. You cannot use them in your templates.

Undefined-safe Operator: The ??-> operator, which was a Latte-specific feature created before PHP 8, has been removed. It is a historical relic. Please use the standard PHP nullsafe operator ?->.

Filter Loader The Engine::addFilterLoader() method has been deprecated and removed. It was an inconsistent concept not found elsewhere in Latte.

Date Format The static property Latte\Runtime\Filters::$dateFormat was removed to avoid global state.

New Features

While migrating, you can start enjoying the new features:

  • **Smart HTML

Attributes:** Pass arrays to class and style, auto-drop null attributes.

  • Nullsafe filters: Use {$var?|filter} to skip filtering null values.
  • n:elseif: You can now use n:elseif alongside n:if and n:else.
  • Simplified syntax: Write <div n:if={$cond}> without quotes.
  • Toggle filter: Use |toggle for manual control over boolean attributes.
version: 3.0