-
-
Notifications
You must be signed in to change notification settings - Fork 277
Expand file tree
/
Copy pathsyntax.texy
More file actions
309 lines (200 loc) Β· 9.78 KB
/
syntax.texy
File metadata and controls
309 lines (200 loc) Β· 9.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
Syntax
******
.[perex]
Latte syntax originated from the practical requirements of web designers. We were looking for the most user-friendly syntax, with which you can elegantly write constructs that are otherwise a real challenge. At the same time, all expressions are written exactly the same as in PHP, so you don't have to learn a new language. You simply leverage what you already know.
Below is a minimal template that illustrates several basic elements: tags, n:attributes, comments, and filters.
```latte
{* this is a comment *}
<ul n:if=$items> {* n:if is an n:attribute *}
{foreach $items as $item} {* tag representing a foreach loop *}
<li>{$item|capitalize}</li> {* tag that prints a variable with a filter *}
{/foreach} {* end of the loop *}
</ul>
```
Let's take a closer look at these important elements and how they can help you create an amazing template.
Tags
====
A template contains tags that control the template logic (for example, *foreach* loops) or output expressions. A single delimiter `{ ... }` is used for both, so you don't have to think about which delimiter to use in which situation, unlike other systems. If the `{` character is followed by a quote or space, Latte does not consider it the beginning of a tag, allowing you to use JavaScript constructs, JSON, or CSS rules in your templates without problems.
See the [overview of all tags|tags]. Additionally, you can create your own [custom tags|custom-tags].
Latte Understands PHP
=====================
Inside the tags, you can use PHP expressions that you are familiar with:
- variables
- strings (including HEREDOC and NOWDOC), arrays, numbers, etc.
- [operators |https://www.php.net/manual/en/language.operators.php]
- function and method calls (which can be restricted by [sandbox|sandbox])
- [match |https://www.php.net/manual/en/control-structures.match.php]
- [arrow functions |https://www.php.net/manual/en/functions.arrow.php]
- [first class callable syntax |https://www.php.net/manual/en/functions.first_class_callable_syntax.php]
- multi-line comments `/* ... */`
- etcβ¦
Furthermore, Latte enhances PHP syntax with several [nice extensions |#Syntactic Sugar].
n:attributes
============
Every pair tag, such as `{if} β¦ {/if}`, operating on a single HTML element, can be rewritten in the form of n:attributes. For example, the `{foreach}` in the introductory example could also be written this way:
```latte
<ul n:if=$items>
<li n:foreach="$items as $item">{$item|capitalize}</li>
</ul>
```
The functionality then applies to the HTML element in which it is placed:
```latte
{var $items = ['I', 'β₯', 'Latte']}
<p n:foreach="$items as $item">{$item}</p>
```
outputs:
```latte
<p>I</p>
<p>β₯</p>
<p>Latte</p>
```
Using the `inner-` prefix, we can modify the behavior so that it applies only to the inner part of the element:
```latte
<div n:inner-foreach="$items as $item">
<p>{$item}</p>
<hr>
</div>
```
Outputs:
```latte
<div>
<p>I</p>
<hr>
<p>β₯</p>
<hr>
<p>Latte</p>
<hr>
</div>
```
Or, using the `tag-` prefix, we apply the functionality only to the HTML tags themselves:
```latte
<p><a href={$url} n:tag-if="$url">Title</a></p>
```
Which outputs, depending on the variable `$url`:
```latte
{* when $url is empty *}
<p>Title</p>
{* when $url contains 'https://nette.org' *}
<p><a href="https://nette.org">Title</a></p>
```
However, n:attributes are not only a shortcut for pair tags, there are some pure n:attributes as well, for example the coder's best friend [n:class|tags#n:class] or the very handy [n:href |application:creating-links#In the Presenter Template].
In addition to the syntax using quotes `<div n:if="$foo">`, you can use alternative syntax with curly braces `<div n:if={$foo}>`. The main advantage is that you can freely use both single and double quotes inside `{...}`:
```latte
<div n:if={str_contains($val, "foo")}> ... </div>
```
Smart HTML Attributes .{data-version:3.1}
=========================================
Latte makes working with standard HTML attributes incredibly easy. It handles boolean attributes like `checked` for you, removes attributes containing `null`, and allows you to compose `class` and `style` values using arrays. It even automatically serializes data for `data-` attributes into JSON.
```latte
{* null removes the attribute *}
<div title={$title}>
{* boolean controls presence of boolean attributes *}
<input type="checkbox" checked={$isChecked}>
{* arrays work in class *}
<div class={['btn', 'btn-primary', active => $isActive]}>
{* arrays are JSON-encoded in data- attributes *}
<div data-config={[theme: dark, version: 2]}>
```
Read more in the separate chapter [Smart HTML Attributes|html-attributes].
Filters
=======
See the overview of [standard filters |filters].
Filters are written after the pipe symbol (a preceding space is allowed):
```latte
<h1>{$heading|upper}</h1>
```
Filters can be chained, and they are applied in order from left to right:
```latte
<h1>{$heading|lower|capitalize}</h1>
```
Parameters are entered after the filter name, separated by colons or commas:
```latte
<h1>{$heading|truncate:20,''}</h1>
```
Filters can also be applied to an expression:
```latte
{var $name = ($title|upper) . ($subtitle|lower)}
```
On a block:
```latte
<h1>{block |lower}{$heading}{/block}</h1>
```
Or directly on a value (in combination with the [`{=expr}` |tags#Printing] tag):
```latte
<h1>{=' Hello world '|trim}<h1>
```
If the value can be `null` and you want to avoid applying the filter in that case, use the [nullsafe filter |filters#Nullsafe Filters] `?|`:
```latte
<h1>{$heading?|upper}</h1>
```
Dynamic HTML Tags .{data-version:3.0.9}
=======================================
Latte supports dynamic HTML tags, which are useful when you need flexibility in tag names:
```latte
<h{$level}>Heading</h{$level}>
```
For example, the code above can generate `<h1>Heading</h1>` or `<h2>Heading</h2>` depending on the value of the variable `$level`. Dynamic HTML tags in Latte must always be paired. Their alternative is [n:tag |tags#n:tag].
Because Latte is a secure templating system, it checks that the resulting tag name is valid and does not contain any unwanted or malicious values. It also ensures that the end tag name always matches the opening tag name.
Comments
========
Comments are written this way and do not get into the output:
```latte
{* this is a comment in Latte *}
```
PHP comments work inside tags:
```latte
{include 'file.info', /* value: 123 */}
```
Syntactic Sugar
===============
Strings Without Quotation Marks
-------------------------------
Quotation marks can be omitted for simple strings:
```latte
as in PHP: {var $arr = ['hello', 'btn--default', 'β¬']}
abbreviated: {var $arr = [hello, btn--default, β¬]}
```
Simple strings are those composed purely of letters, digits, underscores, hyphens, and periods. They must not start with a digit and must not start or end with a hyphen. They must not consist solely of uppercase letters and underscores, as they are then considered constants (e.g., `PHP_VERSION`). And they must not conflict with the keywords: `and`, `array`, `clone`, `default`, `false`, `in`, `instanceof`, `new`, `null`, `or`, `return`, `true`, `xor`.
Constants
---------
Use the global namespace separator to distinguish global constants from simple strings:
```latte
{if \PROJECT_ID === 1} ... {/if}
```
This notation is entirely valid in PHP itself, where the slash indicates that the constant is in the global namespace.
Short Ternary Operator
----------------------
If the third value of the ternary operator is empty, it can be omitted:
```latte
as in PHP: {$stock ? 'In stock' : ''}
abbreviated: {$stock ? 'In stock'}
```
Modern Key Notation in Arrays
-----------------------------
Array keys can be written similarly to named parameters when calling functions:
```latte
as in PHP: {var $arr = ['one' => 'item 1', 'two' => 'item 2']}
modern: {var $arr = [one: 'item 1', two: 'item 2']}
```
Filters
-------
Filters can be used for any expression; just enclose the whole expression in parentheses:
```latte
{var $content = ($text|truncate: 30|upper)}
```
Operator `in`
-------------
The `in` operator can replace the `in_array()` function. The comparison is always strict:
```latte
{* like in_array($item, $items, true) *}
{if $item in $items}
...
{/if}
```
A Window into History
---------------------
Over its history, Latte introduced several syntactic sugar features that appeared in PHP itself a few years later. For example, in Latte, it was possible to write arrays as `[1, 2, 3]` instead of `array(1, 2, 3)` or use the nullsafe operator `$obj?->foo` long before it was possible in PHP itself. Latte also introduced the array expansion operator `(expand) $arr`, which is equivalent to today's `...$arr` operator from PHP.
PHP Limitations in Latte
========================
Only PHP expressions can be written in Latte. That is, statements ending with a semicolon cannot be used. You cannot declare classes or use [control structures |https://www.php.net/manual/en/language.control-structures.php], such as `if`, `foreach`, `switch`, `return`, `try`, `throw`, and others, for which Latte offers its [tags|tags]. You also cannot use [attributes |https://www.php.net/manual/en/language.attributes.php], [backticks |https://www.php.net/manual/en/language.operators.execution.php], or some [magic constants |https://www.php.net/manual/en/language.constants.magic.php]. You cannot use `unset`, `echo`, `include`, `require`, `exit`, `eval` either, because they are not functions but special PHP language constructs, and thus not expressions. Only multi-line comments `/* ... */` are supported.
However, these limitations can be bypassed by activating the [RawPhpExtension |develop#RawPhpExtension] extension, which allows you to use any PHP code within the `{php ...}` tag at the template author's responsibility.