You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
5
+
6
+
This guide summarizes the breaking changes and how to handle them.
7
+
8
+
Latte 3.1 requires **PHP 8.2** or newer.
9
+
10
+
11
+
Smart Attributes and Migration
12
+
==============================
13
+
14
+
The most significant change in Latte 3.1 is the new behavior of [Smart Attributes |/html-attributes]. This affects how `null` values and boolean values in `data-` attributes are rendered.
15
+
16
+
1. **`null` values:** Previously, `title={$null}` rendered as `title=""`. Now, the attribute is completely dropped.
17
+
2. **`data-` attributes:** Previously, `data-foo={true}` rendered as `data-foo="1"`. Now, it renders as `data-foo="true"`.
18
+
19
+
To help you identify places where the output has changed in your application, Latte provides a migration tool.
20
+
21
+
22
+
Migration Warnings
23
+
------------------
24
+
25
+
You can enable [migration warnings |/develop#Migration Warnings], which will warn you during rendering if the output differs from Latte 3.0.
26
+
27
+
```php
28
+
$latte = new Latte\Engine;
29
+
$latte->setMigrationWarnings();
30
+
```
31
+
32
+
When enabled, check your application logs or Tracy bar for `E_USER_WARNING`s. Each warning will point to the specific file, line, and column.
33
+
34
+
**How to resolve warnings:**
35
+
36
+
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:
37
+
38
+
```latte
39
+
<div class="{$var|accept}"></div>
40
+
```
41
+
42
+
If you want to keep the attribute as empty (e.g. `title=""`) instead of dropping it, use the null coalescing operator:
43
+
44
+
```latte
45
+
<div title={$var ?? ''}></div>
46
+
```
47
+
48
+
Or, if you strictly require the old behavior (e.g. `"1"` for `true`), explicitly cast the value to string:
49
+
50
+
```latte
51
+
<div data-foo={(string) $bool}></div>
52
+
```
53
+
54
+
**After you resolve all warnings:**
55
+
56
+
Once all warnings are resolved, disable migration warnings and **remove all** `|accept` filters from your templates, as they are no longer needed.
57
+
58
+
59
+
Strict Types
60
+
============
61
+
62
+
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.
63
+
64
+
If you cannot fix the types immediately, you can disable this behavior:
65
+
66
+
```php
67
+
$latte->setStrictTypes(false);
68
+
```
69
+
70
+
71
+
Global Constants
72
+
================
73
+
74
+
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 `\`.
75
+
76
+
```latte
77
+
{* Old way (now interpreted as string 'PHP_VERSION') *}
78
+
{if PHP_VERSION > ...}
79
+
80
+
{* New way (correctly interpreted as constant) *}
81
+
{if \PHP_VERSION > ...}
82
+
```
83
+
84
+
This change prevents ambiguity and allows you to use unquoted strings more freely.
85
+
86
+
87
+
Removed Features
88
+
================
89
+
90
+
**Reserved Variables**
91
+
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.
92
+
93
+
**Undefined-safe Operator `??->`**
94
+
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 `?->` or the null coalescing operator `??`.
95
+
96
+
**Filter Loader**
97
+
The `Engine::addFilterLoader()` method has been deprecated and removed. It was an inconsistent concept not found elsewhere in Latte.
98
+
99
+
**Date Format**
100
+
The static property `Latte\Runtime\Filters::$dateFormat` was removed to avoid global state.
101
+
102
+
103
+
Summary of New Features
104
+
=======================
105
+
106
+
While migrating, you can start enjoying the new features:
107
+
108
+
- **Smart Attributes:** Pass arrays to `class` and `style`, auto-drop `null` attributes.
109
+
- **Nullsafe filters:** Use `{$var?|filter}` to skip filtering null values.
110
+
- **`n:elseif`:** You can now use `n:elseif` alongside `n:if` and `n:else`.
111
+
- **Simplified syntax:** Write `<div n:if={$cond}>` without quotes.
112
+
- **Toggle filter:** Use `|toggle` for manual control over boolean attributes.
Copy file name to clipboardExpand all lines: latte/en/filters.texy
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -142,7 +142,7 @@ Filters
142
142
143
143
accept .[filter]{data-version:3.1}
144
144
----------------------------------
145
-
The filter is used during [migration from Latte 3.0|html-attributes#Migration from Latte 3.0] to acknowledge that you've reviewed the attribute behavior change and accept it. It does not modify the value.
145
+
The filter is used during [migration from Latte 3.0|cookbook/migration-from-latte-30] to acknowledge that you've reviewed the attribute behavior change and accept it. It does not modify the value.
146
146
147
147
This is a temporary tool. Once the migration is complete and migration warnings are disabled, you should remove this filter from your templates.
Copy file name to clipboardExpand all lines: latte/en/html-attributes.texy
+22-45Lines changed: 22 additions & 45 deletions
Original file line number
Diff line number
Diff line change
@@ -12,14 +12,13 @@ HTML uses special attributes like `checked`, `disabled`, `selected`, or `hidden`
12
12
13
13
Latte 3.1 handles them automatically. You can pass any expression to the attribute. If it is truthy, the attribute is rendered. If it is falsey (e.g. `false`, `null`, `0`, or an empty string), the attribute is completely omitted.
14
14
15
-
This means you can say goodbye to cumbersome macro conditions or `n:attr`:
15
+
This means you can say goodbye to cumbersome macro conditions or `n:attr` and simply use:
If `$isReadOnly` is `true` and `$isDisabled` is `false`, it renders:
21
+
If `$isDisabled` is `false` and `$isReadOnly` is `true`, it renders:
23
22
24
23
```latte
25
24
<input type="text" readonly>
@@ -41,7 +40,7 @@ In Latte 3.1, a new universal rule applies: **A value of `null` means the attrib
41
40
42
41
If `$title` is `null`, the output is `<div></div>`. If it contains a string, e.g. "Hello", the output is `<div title="Hello"></div>`. Thanks to this, you don't have to wrap attributes in conditions.
43
42
44
-
If you use filters, keep in mind that they usually convert `null` to a string (e.g. empty string). To prevent this, use the [nullsafe operator |filters#Nullsafe Filters] `?|`:
43
+
If you use filters, keep in mind that they usually convert `null` to a string (e.g. empty string). To prevent this, use the [nullsafe filter |filters#Nullsafe Filters] `?|`:
45
44
46
45
```latte
47
46
<div title="{$title?|upper}"></div>
@@ -51,26 +50,20 @@ If you use filters, keep in mind that they usually convert `null` to a string (e
51
50
Classes
52
51
=======
53
52
54
-
You can pass an array to the `class` attribute, and Latte will automatically join the items with spaces.
55
-
56
-
This is perfect for conditional classes: if the array is associative, the keys are used as class names and the values as conditions. The class is rendered only if the condition is true.
53
+
You can pass an array to the `class` attribute. This is perfect for conditional classes: if the array is associative, the keys are used as class names and the values as conditions. The class is rendered only if the condition is true.
This behavior is not limited to `class`. It works for **any HTML attribute** that expects a space-separated list of values, such as `itemprop`, `rel`, `sandbox`, etc.
@@ -124,7 +117,7 @@ Aria Attributes
124
117
The WAI-ARIA specification requires text values `"true"` and `"false"` for boolean values. Latte handles this automatically for `aria-` attributes:
Latte 3.1 checks attribute types to prevent you from printing nonsense.
141
-
142
-
1. **Standard attributes (href, src, id...):** Expect a string or `null`. If they receive an array, object or boolean, Latte throws a warning and the attribute is omitted.
143
-
2. **Boolean attributes (checked...):** Expect a boolean.
144
-
3. **Special attributes (class, style, data-, aria-):** Have their own rules described above.
145
-
146
-
This check helps you discover bugs in your code early.
147
-
148
-
149
-
Migration from Latte 3.0
150
-
========================
151
-
152
-
Since the behavior of `null` changes (it used to print `""`, now it doesn't print anything) and `data-` attributes (booleans used to print `1`/`""`, now `"true"`/`"false"`), Latte offers a tool to help with migration.
133
+
Have you ever seen `<input value="Array">` in your generated HTML? It's a classic bug that often goes unnoticed. Latte 3.1 introduces strict type checking for HTML attributes to make your templates more resilient against such oversight.
153
134
154
-
You can enable **migration warnings** (see [Develop |develop#Migration Warnings]), which will warn you during rendering if the output differs from Latte 3.0.
135
+
Latte knows which attributes are which and what values they expect:
155
136
156
-
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:
137
+
- **Standard attributes** (like `href`, `id`, `value`, `placeholder`...) expect a value that can be rendered as text. This includes strings, numbers, or objects implementing `__toString`. `null` is also accepted (it drops the attribute). However, if you accidentally pass an array or a generic object, Latte won't print "Array". Instead, it triggers a warning and intelligently ignores the invalid value.
138
+
- **Boolean attributes** (like `checked`, `disabled`...) accept any type, as their presence is determined by truthy/falsey logic.
139
+
- **Smart attributes** (like `class`, `style`, `data-`...) specifically handle arrays and objects as valid inputs.
157
140
158
-
```latte
159
-
<div class="{$var|accept}"></div>
160
-
```
141
+
This check ensures that your application doesn't produce invalid HTML.
161
142
162
-
If you want to keep the attribute as empty (e.g. `title=""`) instead of dropping it, use the null coalescing operator:
143
+
Moreover, when an error is detected, the warning message is incredibly precise. It tells you not just what went wrong, but exactly where: **the file, line, and even the column** of the problematic attribute. You will find the bug instantly.
163
144
164
-
```latte
165
-
<div title={$var ?? ''}></div>
166
-
```
167
145
168
-
Or, if you strictly require the old behavior (e.g. `"1"` for `true`), explicitly cast the value to string:
146
+
Migration from Latte 3.0
147
+
========================
169
148
170
-
```latte
171
-
<div data-foo={(string) $bool}></div>
172
-
```
149
+
Since the behavior of `null` (it used to print `""`, now it drops the attribute) and `data-` attributes (booleans used to print `"1"`/`""`, now `"true"`/`"false"`) has changed, you might need to update your templates.
173
150
174
-
Once all warnings are resolved, disable migration warnings and **remove all** `|accept` filters from your templates, as they are no longer needed.
151
+
For a smooth transition, Latte provides a migration mode that highlights differences. Read the detailed guide [Migration from Latte 3.0 to 3.1|cookbook/migration-from-latte-30].
0 commit comments