Skip to content

Commit 9ebd98f

Browse files
committed
x
1 parent 47600d6 commit 9ebd98f

4 files changed

Lines changed: 136 additions & 46 deletions

File tree

latte/en/cookbook/@home.texy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Example codes and recipes for accomplishing common tasks with Latte.
88
- [Passing variables across templates |passing-variables]
99
- [Everything you always wanted to know about grouping |grouping]
1010
- [How to write SQL queries in Latte? |how-to-write-sql-queries-in-latte]
11+
- [Migration from Latte 3.0 |migration-from-latte-30]
1112
- [Migration from Latte 2 |migration-from-latte2]
1213
- [Migration from PHP |migration-from-php]
1314
- [Migration from Twig |migration-from-twig]
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
Migration from Latte 3.0
2+
************************
3+
4+
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.

latte/en/filters.texy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ Filters
142142

143143
accept .[filter]{data-version:3.1}
144144
----------------------------------
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.
146146

147147
This is a temporary tool. Once the migration is complete and migration warnings are disabled, you should remove this filter from your templates.
148148

latte/en/html-attributes.texy

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ HTML uses special attributes like `checked`, `disabled`, `selected`, or `hidden`
1212

1313
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.
1414

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

1717
```latte
1818
<input type="text" disabled={$isDisabled} readonly={$isReadOnly}>
19-
</form>
2019
```
2120

22-
If `$isReadOnly` is `true` and `$isDisabled` is `false`, it renders:
21+
If `$isDisabled` is `false` and `$isReadOnly` is `true`, it renders:
2322

2423
```latte
2524
<input type="text" readonly>
@@ -41,7 +40,7 @@ In Latte 3.1, a new universal rule applies: **A value of `null` means the attrib
4140

4241
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.
4342

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] `?|`:
4544

4645
```latte
4746
<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
5150
Classes
5251
=======
5352

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.
5754

5855
```latte
59-
<div class="header">
60-
<button class={[
61-
btn,
62-
btn-primary,
63-
active => $isActive,
64-
]}>Press me</button>
65-
</div>
56+
<button class={[
57+
btn,
58+
btn-primary,
59+
active => $isActive,
60+
]}>Press me</button>
6661
```
6762

6863
If `$isActive` is true, it renders:
6964

7065
```latte
71-
<div class="header">
72-
<button class="btn btn-primary active">Press me</button>
73-
</div>
66+
<button class="btn btn-primary active">Press me</button>
7467
```
7568

7669
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
124117
The WAI-ARIA specification requires text values `"true"` and `"false"` for boolean values. Latte handles this automatically for `aria-` attributes:
125118

126119
```latte
127-
<button aria-expanded={true} aria-checked={false}></button>
120+
<button aria-expanded={=true} aria-checked={=false}></button>
128121
```
129122

130123
Outputs:
@@ -137,38 +130,22 @@ Outputs:
137130
Type Checking
138131
=============
139132

140-
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.
153134

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

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.
157140

158-
```latte
159-
<div class="{$var|accept}"></div>
160-
```
141+
This check ensures that your application doesn't produce invalid HTML.
161142

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.
163144

164-
```latte
165-
<div title={$var ?? ''}></div>
166-
```
167145

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+
========================
169148

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.
173150

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

Comments
 (0)