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
Takto jednoduše můžeme do šablon předat jakékoliv proměnné. Při vývoji robustních aplikací ale bývá užitečnější se omezit. Například tak, že explicitně nadefinujeme výčet proměnných, které šablona očekává, a jejich typů. Díky tomu nám bude moci PHP kontrolovat typy, IDE správně našeptávat a statická analýza odhalovat chyby.
124
123
125
-
A jak takový výčet nadefinujeme? Jednoduše v podobě třídy a její properties. Pojmenujeme ji podobně jako presenter, jen s `Template` na konci:
124
+
Výchozí proměnné
125
+
----------------
126
+
127
+
Presentery a komponenty předávají do šablon několik užitečných proměnných automaticky:
128
+
129
+
- `$basePath` je absolutní URL cesta ke kořenovému adresáři (např. `/eshop`)
130
+
- `$baseUrl` je absolutní URL ke kořenovému adresáři (např. `http://localhost/eshop`)
131
+
- `$user` je objekt [reprezentující uživatele |security:authentication]
132
+
- `$presenter` je aktuální presenter
133
+
- `$control` je aktuální komponenta nebo presenter
134
+
- `$flashes` pole [zpráv |presenters#Flash zprávy] zaslaných funkcí `flashMessage()`
135
+
136
+
Pokud používáte vlastní třídu šablony, tyto proměnné se předají, pokud pro ně vytvoříte property.
137
+
138
+
139
+
Typově bezpečné šablony
140
+
-----------------------
141
+
142
+
Při vývoji robustních aplikací je užitečné explicitně nadefinovat, jaké proměnné šablona očekává a jakého jsou typu. Získáte tak typovou kontrolu v PHP, chytré našeptávání v IDE a schopnost statické analýzy odhalovat chyby.
143
+
144
+
Jak takový výčet nadefinovat? Jednoduše v podobě třídy s properties reprezentujícími proměnné šablony. Pojmenujeme ji podobně jako presenter, jen s `Template` na konci:
126
145
127
146
```php
128
147
/**
@@ -141,22 +160,22 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
141
160
}
142
161
```
143
162
144
-
Objekt `$this->template` v presenteru bude nyní instancí třídy `ArticleTemplate`. Takže PHP bude při zápisu kontrolovat deklarované typy. A počínaje verzí PHP 8.2 upozorní i na zápis do neexistující proměnné, v předchozích verzích lze téhož dosáhnout použitím traity [Nette\SmartObject |utils:smartobject].
163
+
Objekt `$this->template` v presenteru bude nyní instancí třídy `ArticleTemplate`. PHP tak bude při zápisu kontrolovat deklarované typy.
145
164
146
-
Anotace `@property-read` je určená pro IDE a statickou analýzu, díky ní bude fungovat našeptávání, viz "PhpStorm and code completion for $this->template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template.
165
+
Anotace `@property-read` slouží pro IDE a statickou analýzu, díky ní bude fungovat našeptávání, viz "PhpStorm and code completion for $this->template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template.
147
166
148
167
[* phpstorm-completion.webp *]
149
168
150
-
Luxusu našeptávání si můžete dopřát i v šablonách, stačí do PhpStorm nainstalovat plugin pro Latte a uvést na začátek šablony název třídy, více v článku "Latte: jak na typový systém":https://blog.nette.org/cs/latte-jak-na-typovy-system:
169
+
Našeptávání můžete využít i přímo v šablonách. Stačí do PhpStorm nainstalovat plugin pro Latte a uvést na začátek šablony název třídy parametrů šablony, více v článku "Latte: jak na typový systém":https://blog.nette.org/cs/latte-jak-na-typovy-system:
Takto fungují i šablony v komponentách, stačí jen dodržet jmennou konvenci a pro komponentu např. `FifteenControl` vytvořit třídu šablony `FifteenTemplate`.
176
+
Totéž platí i pro komponenty. Stačí dodržet jmennou konvenci a pro komponentu např. `FifteenControl` vytvořit třídu parametrů `FifteenTemplate`.
158
177
159
-
Pokud potřebujete vytvořit `$template` jako instanci jiné třídy, využijte metodu `createTemplate()`:
178
+
Pokud potřebujete použít jinou třídu parametrů, využijte metodu `createTemplate()`:
160
179
161
180
```php
162
181
public function renderDefault(): void
@@ -169,21 +188,6 @@ public function renderDefault(): void
169
188
```
170
189
171
190
172
-
Výchozí proměnné
173
-
----------------
174
-
175
-
Presentery a komponenty předávají do šablon několik užitečných proměnných automaticky:
176
-
177
-
- `$basePath` je absolutní URL cesta ke kořenovému adresáři (např. `/eshop`)
178
-
- `$baseUrl` je absolutní URL ke kořenovému adresáři (např. `http://localhost/eshop`)
179
-
- `$user` je objekt [reprezentující uživatele |security:authentication]
180
-
- `$presenter` je aktuální presenter
181
-
- `$control` je aktuální komponenta nebo presenter
182
-
- `$flashes` pole [zpráv |presenters#Flash zprávy] zaslaných funkcí `flashMessage()`
183
-
184
-
Pokud používáte vlastní třídu šablony, tyto proměnné se předají, pokud pro ně vytvoříte property.
185
-
186
-
187
191
Vytváření odkazů
188
192
----------------
189
193
@@ -205,21 +209,67 @@ Více informací najdete v kapitole [Vytváření odkazů URL|creating-links].
205
209
Vlastní filtry, značky apod.
206
210
----------------------------
207
211
208
-
Šablonovací systém Latte lze rozšířit o vlastní filtry, funkce, značky apod. Lze tak učinit přímo v metodě `render<View>` nebo `beforeRender()`:
212
+
Šablonovací systém Latte lze rozšířit o vlastní filtry, funkce, značky a další prvky. K dispozici jsou tři způsoby, jak to udělat, od nejrychlejších ad-hoc řešení až po architektonický přístup pro celou aplikaci.
213
+
214
+
**Ad-hoc v metodách presenteru**
215
+
216
+
Nejrychlejší způsob je přidat filtr nebo funkci přímo v kódu presenteru či komponenty. V presenteru je k tomu vhodná metoda `beforeRender()` nebo `render<View>()`:
Pro složitější logiku můžete konfigurovat přímo objekt `Latte\Engine`:
238
+
239
+
```php
240
+
protected function beforeRender(): void
241
+
{
217
242
$latte = $this->template->getLatte();
218
243
$latte->setMigrationWarnings();
219
244
}
220
245
```
221
246
222
-
Latte ve verzi 3 nabízí pokročilejší způsob a to vytvoření si [extension |latte:extending-latte#Latte Extension] pro každý webový projekt. Kusý příklad takové třídy:
247
+
**Pomocí atributů**
248
+
249
+
Elegantní způsob je definovat filtry a funkce jako metody přímo ve [třídě parametrů šablony|#Typově bezpečné šablony] presenteru nebo komponenty a označit je atributy:
250
+
251
+
```php
252
+
class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
253
+
{
254
+
#[Latte\Attributes\TemplateFilter]
255
+
public function money(float $val): string
256
+
{
257
+
return round($val) . ' Kč';
258
+
}
259
+
260
+
#[Latte\Attributes\TemplateFunction]
261
+
public function isWeekend(DateTimeInterface $date): bool
262
+
{
263
+
return $date->format('N') >= 6
264
+
}
265
+
}
266
+
```
267
+
268
+
Latte automaticky rozpozná a zaregistruje metody označené těmito atributy. Název filtru nebo funkce v šabloně odpovídá názvu metody. Tyto metody nesmí být privátní.
269
+
270
+
**Globálně pomocí Extension**
271
+
272
+
Předchozí způsoby jsou vhodné pro filtry a funkce, které potřebujete jen v konkrétním presenteru nebo komponentě, nikoliv v celé aplikaci. Pro celou aplikaci je nejvhodnější vytvořit si [extension |latte:extending-latte#Latte Extension]. Jde o třídu, která centralizuje všechna rozšíření Latte pro celý projekt. Kusý příklad:
223
273
224
274
```php
225
275
namespace App\Presentation\Accessory;
@@ -251,18 +301,25 @@ final class LatteExtension extends Latte\Extension
251
301
];
252
302
}
253
303
304
+
private function filterTimeAgoInWords(DateTimeInterface $time): string
305
+
{
306
+
// ...
307
+
}
308
+
254
309
// ...
255
310
}
256
311
```
257
312
258
-
Zaregistrujeme ji pomocí [konfigurace |configuration#Šablony Latte]:
313
+
Extension zaregistrujeme pomocí [konfigurace |configuration#Šablony Latte]:
259
314
260
315
```neon
261
316
latte:
262
317
extensions:
263
318
- App\Presentation\Accessory\LatteExtension
264
319
```
265
320
321
+
Výhodou extension je, že lze využít dependency injection, mít přístup k modelové vrstvě aplikace a všechna rozšíření mít přehledně na jednom místě. Extension umožnuje definovat i vlastní značky, providery, průchody pro Latte kompilátor a další.
Copy file name to clipboardExpand all lines: application/en/templates.texy
+88-31Lines changed: 88 additions & 31 deletions
Original file line number
Diff line number
Diff line change
@@ -111,18 +111,37 @@ Using `$this->setLayout(false)` or the `{layout none}` tag inside the template d
111
111
The files where layout templates are looked up can be changed by overriding the [formatLayoutTemplateFiles() |api:Nette\Application\UI\Presenter::formatLayoutTemplateFiles()] method, which returns an array of possible file names.
112
112
113
113
114
-
Variables in the Template
115
-
-------------------------
114
+
Template Variables
115
+
------------------
116
116
117
-
Variables are passed to the template by writing them to `$this->template`, and then they are available in the template as local variables:
117
+
Variables are passed to templates by writing them to `$this->template`. They then become available in the template as local variables:
This way, we can easily pass any variables to templates. However, when developing robust applications, it is often more useful to impose limitations. For example, by explicitly defining a list of variables that the template expects and their types. This allows PHP to perform type checking, the IDE to provide correct autocompletion, and static analysis to detect errors.
124
123
125
-
And how do we define such a list? Simply in the form of a class and its properties. We name it similarly to the presenter, but with `Template` at the end:
124
+
Default Variables
125
+
-----------------
126
+
127
+
Presenters and components automatically pass several useful variables to templates:
128
+
129
+
- `$basePath` is the absolute URL path to the root directory (e.g., `/eshop`)
130
+
- `$baseUrl` is the absolute URL to the root directory (e.g., `http://localhost/eshop`)
131
+
- `$user` is an object [representing the user |security:authentication]
132
+
- `$presenter` is the current presenter
133
+
- `$control` is the current component or presenter
134
+
- `$flashes` is an array of [messages |presenters#Flash Messages] sent by the `flashMessage()` function
135
+
136
+
If you use a custom template class, these variables are passed if you create a property for them.
137
+
138
+
139
+
Type-Safe Templates
140
+
-------------------
141
+
142
+
When developing robust applications, it's useful to explicitly define which variables the template expects and their types. This provides type checking in PHP, smart hints in your IDE, and enables static analysis to catch errors.
143
+
144
+
How do you define such a list? Simply as a class with properties representing template variables. Name it similarly to the presenter, just with `Template` at the end:
126
145
127
146
```php
128
147
/**
@@ -141,22 +160,22 @@ class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
141
160
}
142
161
```
143
162
144
-
The `$this->template` object in the presenter will now be an instance of the `ArticleTemplate` class. So PHP will check the declared types upon writing. And starting from PHP 8.2, it will also warn about writing to a non-existent variable; in previous versions, the same can be achieved using the [Nette\SmartObject |utils:smartobject] trait.
163
+
The `$this->template` object in the presenter will now be an instance of the `ArticleTemplate` class. PHP will thus check the declared types when writing.
145
164
146
-
The `@property-read` annotation is intended for IDEs and static analysis; thanks to it, autocompletion will work, see "PhpStorm and code completion for $this->template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template.
165
+
The `@property-read` annotation is for the IDE and static analysis, enabling code completion, see "PhpStorm and code completion for $this->template":https://blog.nette.org/en/phpstorm-and-code-completion-for-this-template.
147
166
148
167
[* phpstorm-completion.webp *]
149
168
150
-
You can enjoy the luxury of autocompletion in templates too; just install the Latte plugin for PhpStorm and specify the class name at the beginning of the template, more in the article "Latte: How to Use Type System":https://blog.nette.org/en/latte-how-to-use-type-system:
169
+
You can also use code completion directly in templates. Just install the Latte plugin for PhpStorm and specify the template parameter class name at the beginning of the template, more in the article "Latte: how to use the type system":https://blog.nette.org/en/latte-how-to-use-type-system:
This is also how templates work in components; just follow the naming convention and create a template class `FifteenTemplate` for a component like `FifteenControl`.
176
+
The same applies to components. Just follow the naming convention and create a parameter class `FifteenTemplate` for a component like `FifteenControl`.
158
177
159
-
If you need to create `$template` as an instance of another class, use the `createTemplate()` method:
178
+
If you need to use a different parameter class, use the `createTemplate()` method:
160
179
161
180
```php
162
181
public function renderDefault(): void
@@ -169,21 +188,6 @@ public function renderDefault(): void
169
188
```
170
189
171
190
172
-
Default Variables
173
-
-----------------
174
-
175
-
Presenters and components automatically pass several useful variables to templates:
176
-
177
-
- `$basePath` is the absolute URL path to the root directory (e.g., `/eshop`)
178
-
- `$baseUrl` is the absolute URL to the root directory (e.g., `http://localhost/eshop`)
179
-
- `$user` is an object [representing the user |security:authentication]
180
-
- `$presenter` is the current presenter
181
-
- `$control` is the current component or presenter
182
-
- `$flashes` is an array of [messages |presenters#Flash Messages] sent by the `flashMessage()` function
183
-
184
-
If you use a custom template class, these variables are passed if you create a property for them.
185
-
186
-
187
191
Creating Links
188
192
--------------
189
193
@@ -205,21 +209,67 @@ More information can be found in the chapter [Creating URL Links|creating-links]
205
209
Custom Filters, Tags, etc.
206
210
--------------------------
207
211
208
-
The Latte templating system can be extended with custom filters, functions, tags, etc. This can be done directly in the `render<View>` or `beforeRender()` method:
212
+
The Latte templating system can be extended with custom filters, functions, tags, and other elements. There are three approaches available, ranging from quick ad-hoc solutions to architectural patterns for entire applications.
213
+
214
+
**Ad-hoc in Presenter Methods**
215
+
216
+
The quickest approach is adding filters or functions directly in presenter or component code. In presenters, the `beforeRender()` or `render<View>()` methods work well for this:
For more complex logic, you can configure the `Latte\Engine` object directly:
238
+
239
+
```php
240
+
protected function beforeRender(): void
241
+
{
217
242
$latte = $this->template->getLatte();
218
243
$latte->setMigrationWarnings();
219
244
}
220
245
```
221
246
222
-
Latte version 3 offers a more advanced way by creating an [extension |latte:extending-latte#Latte Extension] for each web project. Here is a brief example of such a class:
247
+
**Using Attributes**
248
+
249
+
A more elegant approach is defining filters and functions as methods directly in the presenter or component's [template parameter class|#Type-safe templates], marked with attributes:
250
+
251
+
```php
252
+
class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
253
+
{
254
+
#[Latte\Attributes\TemplateFilter]
255
+
public function money(float $val): string
256
+
{
257
+
return '$' . number_format($val, 2);
258
+
}
259
+
260
+
#[Latte\Attributes\TemplateFunction]
261
+
public function isWeekend(DateTimeInterface $date): bool
262
+
{
263
+
return $date->format('N') >= 6
264
+
}
265
+
}
266
+
```
267
+
268
+
Latte automatically discovers and registers methods marked with these attributes. The filter or function name in templates matches the method name. These methods must not be private.
269
+
270
+
**Globally Using Extensions**
271
+
272
+
The previous approaches suit filters and functions needed only in specific presenters or components, not application-wide. For the entire application, creating an [extension |latte:extending-latte#Latte Extension] works best. This class centralizes all Latte extensions for your project. A brief example:
223
273
224
274
```php
225
275
namespace App\Presentation\Accessory;
@@ -251,18 +301,25 @@ final class LatteExtension extends Latte\Extension
251
301
];
252
302
}
253
303
304
+
private function filterTimeAgoInWords(DateTimeInterface $time): string
305
+
{
306
+
// ...
307
+
}
308
+
254
309
// ...
255
310
}
256
311
```
257
312
258
-
We register it using [configuration |configuration#Latte Templates]:
313
+
Register the extension through [configuration |configuration#Latte Templates]:
259
314
260
315
```neon
261
316
latte:
262
317
extensions:
263
318
- App\Presentation\Accessory\LatteExtension
264
319
```
265
320
321
+
Extensions offer several advantages: dependency injection support, access to your application's model layer, and centralized management of all extensions. They also support custom tags, providers, compiler passes, and more.
0 commit comments