-
- {foreach $list as $id => $item}
-
- {$item} обновить - {/foreach} -
-
+ {foreach $items as $id => $item}
+
- {$item} + {/foreach} +
-
- {foreach $list as $id => $item}
-
- {$item} обновить - {/foreach} -
Проголосуйте, пожалуйста
+Гласувайте
{control poll} ``` -Холивудски стил .[#toc-hollywood-style] -======================================= +Hollywood style +=============== -Компонентите обикновено използват един страхотен трик, който наричаме холивудски стил. Вероятно знаете това клише, което актьорите често чуват по време на кастингите: "Не се обаждайте на нас, ние ще се обадим на вас". И това е най-важното. +Компонентите обикновено използват една свежа техника, която обичаме да наричаме Hollywood style. Със сигурност познавате крилатата фраза, която толкова често чуват участниците във филмови кастинги: „Не ни звънете, ние ще ви се обадим“. И точно за това става въпрос. -В Nette, вместо постоянно да задавате въпроси ("Подадена ли е формата?", "Валидна ли е?" или "Кликна ли някой върху този бутон?"), казвате на фреймуърка "Когато това се случи, извикайте този метод" и оставяте по-нататъшната работа върху него. Ако програмирате на JavaScript, този стил на програмиране ви е познат. Пишете функции, които се извикват при настъпване на определено събитие. И двигателят им предава съответните параметри. +В Nette, вместо постоянно да се налага да питате нещо („беше ли изпратен формулярът?“, „беше ли валиден?“ или „натисна ли потребителят този бутон?“), казвате на фреймуърка „когато това се случи, извикай този метод“ и оставяте по-нататъшната работа на него. Ако програмирате на JavaScript, този стил на програмиране ви е добре познат. Пишете функции, които се извикват, когато настъпи определено събитие. И езикът им предава съответните параметри. -Това изцяло променя начина на писане на приложения. Колкото повече задачи можете да делегирате на рамката, толкова по-малко работа ще трябва да свършите. И колкото по-малко можете да забравите. +Това напълно променя гледната точка към писането на приложения. Колкото повече задачи можете да оставите на фреймуърка, толкова по-малко работа имате вие. И толкова по-малко неща можете да пропуснете. -Как да напишем компонент .[#toc-how-to-write-a-component] -========================================================= +Пишем компонент +=============== -Под компонент обикновено разбираме потомък на класа [api:Nette\Application\UI\Control]. Самият презентатор [api:Nette\Application\UI\Presenter] също е потомък на класа `Control`. +Под понятието компонент обикновено разбираме наследник на клас [api:Nette\Application\UI\Control]. (По-точно би било да се използва терминът „controls“, но „контроли“ на български има съвсем различно значение и по-скоро се е наложило „компоненти“.) Самият презентер [api:Nette\Application\UI\Presenter] между другото също е наследник на клас `Control`. ```php .{file:PollControl.php} use Nette\Application\UI\Control; @@ -84,22 +84,22 @@ class PollControl extends Control ``` -Изобразяване на .[#toc-rendering] -================================= +Рендиране +========= -Вече знаем, че тагът `{control componentName}` се използва за визуализиране на компонент. Всъщност се извиква методът `render()` на компонента, в който ние се грижим за рендирането. Както и в презентатора, имаме шаблон [Latte |latte:] в променливата `$this->template`, на който подаваме параметри. За разлика от използването в презентатора, тук трябва да посочим файла на шаблона и да го оставим да се визуализира: +Вече знаем, че за рендиране на компонент се използва тагът `{control componentName}`. Той всъщност извиква метода `render()` на компонента, в който се грижим за рендирането. На разположение имаме, точно както в презентера, [Latte шаблон|templates] в променливата `$this->template`, на която предаваме параметри. За разлика от презентера, трябва да посочим файла с шаблона и да го накараме да се рендира: ```php .{file:PollControl.php} public function render(): void { - // въвеждаме някои параметри в шаблона + // вмъкваме в шаблона някакви параметри $this->template->param = $value; - //и го визуализирайте + // и го рендираме $this->template->render(__DIR__ . '/poll.latte'); } ``` -Тагът `{control}` ни позволява да предаваме параметри на метода `render()`: +Тагът `{control}` позволява да се предадат параметри на метода `render()`: ```latte {control poll $id, $message} @@ -112,7 +112,7 @@ public function render(int $id, string $message): void } ``` -Понякога един компонент може да се състои от няколко части, които искаме да визуализираме поотделно. За всяка от тях ще създадем различен метод за визуализация, например `renderPaginator()`: +Понякога компонентът може да се състои от няколко части, които искаме да рендираме отделно. За всяка от тях създаваме собствен метод за рендиране, тук в примера например `renderPaginator()`: ```php .{file:PollControl.php} public function renderPaginator(): void @@ -121,107 +121,107 @@ public function renderPaginator(): void } ``` -След това в шаблона го извикваме с: +А в шаблона след това го извикваме с помощта на: ```latte {control poll:paginator} ``` -Полезно е да знаете как даден таг се компилира в PHP код, за да го разберете по-добре. +За по-добро разбиране е добре да знаете как този таг се превежда на PHP. ```latte {control poll} {control poll:paginator 123, 'hello'} ``` -Това е събрано в: +се превежда като: ```php $control->getComponent('poll')->render(); $control->getComponent('poll')->renderPaginator(123, 'hello'); ``` -Методът `getComponent()` връща компонента `poll` и след това за него се извиква съответно методът `render()` или `renderPaginator()`. +Методът `getComponent()` връща компонента `poll` и върху този компонент извиква метода `render()`, респ. `renderPaginator()`, ако в тага след двоеточието е посочен друг начин на рендиране. .[caution] -Ако някъде в параметрите се използва **`=>`**, всички параметри ще бъдат обвити в масив и предадени като първи аргумент: +Внимание, ако някъде в параметрите се появи **`=>`**, всички параметри ще бъдат опаковани в масив и предадени като първи аргумент: ```latte -{control poll, id => 123, message => 'hello'} +{control poll, id: 123, message: 'hello'} ``` -съставен за: +се превежда като: ```php $control->getComponent('poll')->render(['id' => 123, 'message' => 'hello']); ``` -Изобразяване на вложен компонент: +Рендиране на подкомпонент: ```latte {control cartControl-someForm} ``` -съставени в: +се превежда като: ```php $control->getComponent("cartControl-someForm")->render(); ``` -Компонентите, както и презентаторите, автоматично предават няколко полезни променливи на шаблоните: +Компонентите, както и презентерите, предават на шаблоните няколко полезни променливи автоматично: -- `$basePath` - абсолютен URL път до главната директория (напр. `/CD-collection`). -- `$baseUrl` е абсолютният URL адрес на главната директория (напр, `http://localhost/CD-collection`) -- `$user` е обектът, който [представлява потребителя |security:authentication]. -- `$presenter` - настоящ водещ +- `$basePath` е абсолютният URL път до коренната директория (напр. `/eshop`) +- `$baseUrl` е абсолютният URL до коренната директория (напр. `http://localhost/eshop`) +- `$user` е обект [представляващ потребителя |security:authentication] +- `$presenter` е текущият презентер - `$control` е текущият компонент -- `$flashes` е списък на [съобщенията, |#flash-сообщений] изпратени по метода `flashMessage()`. +- `$flashes` масив от [съобщения |#Flash съобщения], изпратени с функцията `flashMessage()` -Сигнал .[#toc-signal] -===================== +Сигнал +====== -Вече знаем, че навигацията в приложението Nette се състои от връзки или пренасочвания към двойки `Presenter:action`. Но какво да правим, ако искаме да извършим действие само на **текущата страница**? Например, промяна на реда на сортиране на колоните в таблица; изтриване на елемент; превключване на светъл/тъмен режим; изпращане на формуляр; гласуване в анкета и т.н. +Вече знаем, че навигацията в Nette приложение се състои в свързване или пренасочване към двойки `Presenter:action`. Но какво, ако просто искаме да извършим действие на **текущата страница**? Например да променим сортирането на колони в таблица; да изтрием елемент; да превключим светъл/тъмен режим; да изпратим формуляр; да гласуваме в анкета; и т.н. -Този тип заявка се нарича сигнал. И как действията извикват методи `actionHello
'; @@ -425,10 +446,55 @@ $this->sendResponse(new Responses\CallbackResponse($callback)); ``` -Допълнително четене .[#toc-further-reading] -=========================================== +Ограничаване на достъпа с `#[Requires]` .{data-version:3.2.2} +------------------------------------------------------------- + +Атрибутът `#[Requires]` предоставя разширени възможности за ограничаване на достъпа до презентери и техните методи. Може да се използва за специфициране на HTTP методи, изискване на AJAX заявка, ограничаване до същия произход (same origin) и достъп само чрез пренасочване (forward). Атрибутът може да се прилага както към класове на презентери, така и към отделни методи `actionГлавная страница
+Homepage
... {/block} ``` -Той дефинира блок `content`, който се вмъква вместо `{include content}` в оформлението, и замества блока `title`, който презаписва `{block title}` в оформлението. Опитайте се да си представите резултата. +Той дефинира блок `content`, който се вмъква на мястото на `{include content}` в лейаута, и също така ре-дефинира блок `title`, с който презаписва `{block title}` в лейаута. Опитайте да си представите резултата. -Търсене на шаблони .[#toc-search-for-templates] ------------------------------------------------ +Търсене на шаблони +------------------ -Пътят към шаблоните се определя от главния модул с помощта на проста логика. Той ще се опита да провери дали има някой от тези файлове, разположен спрямо главната директория на класа, където `-
- {foreach $list as $id => $item}
-
- {$item} update - {/foreach} -
-
+ {foreach $items as $id => $item}
+
- {$item} + {/foreach} +
-
- {foreach $list as $id => $item}
-
- {$item} update - {/foreach} -
Cena: {$price|money}
+ +{if isWeekend($now)} ... {/if} +``` + +Pro složitější logiku můžete konfigurovat přímo objekt `Latte\Engine`: + +```php +protected function beforeRender(): void +{ $latte = $this->template->getLatte(); - $latte->addFilterLoader(/* ... */); + $latte->setFeature(Latte\Feature::MigrationWarnings); } ``` -Latte ve verzi 3 nabízí pokročilejší způsob a to vytvoření si [extension |latte:creating-extension] pro každý webový projekt. Kusý příklad takové třídy: +**Pomocí atributů** + +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: ```php -namespace App\Templating; +class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template +{ + #[Latte\Attributes\TemplateFilter] + public function money(float $val): string + { + return round($val) . ' Kč'; + } + + #[Latte\Attributes\TemplateFunction] + public function isWeekend(DateTimeInterface $date): bool + { + return $date->format('N') >= 6 + } +} +``` + +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í. + +**Globálně pomocí Extension** + +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: + +```php +namespace App\Presentation\Accessory; final class LatteExtension extends Latte\Extension { @@ -203,24 +315,30 @@ final class LatteExtension extends Latte\Extension ]; } + private function filterTimeAgoInWords(DateTimeInterface $time): string + { + // ... + } + // ... } ``` -Zaregistrujeme ji pomocí [konfigurace |configuration#Šablony Latte]: +Extension zaregistrujeme pomocí [konfigurace |configuration#Šablony Latte]: ```neon latte: extensions: - - App\Templating\LatteExtension + - App\Presentation\Accessory\LatteExtension ``` +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ší. + Překládání ---------- -Pokud programujete vícejazyčnou aplikaci, budete nejspíš potřebovat některé texty v šabloně vypsat v různých jazycích. Nette Framework k tomuto účelu definuje rozhraní pro překlad [api:Nette\Localization\Translator], které má jedinou metodu `translate()`. Ta přijímá zprávu `$message`, což zpravidla bývá řetězec, a libovolné další parametry. Úkolem je vrátit přeložený řetězec. -V Nette není žádná výchozí implementace, můžete si vybrat podle svých potřeb z několika hotových řešeních, které najdete na [Componette |https://componette.org/search/localization]. V jejich dokumentaci se dozvíte, jak translator konfigurovat. +Pokud programujete vícejazyčnou aplikaci, budete nejspíš potřebovat některé texty v šabloně vypsat v různých jazycích. Nette Framework k tomuto účelu definuje rozhraní pro překlad [api:Nette\Localization\Translator], které má jedinou metodu `translate()`. Ta přijímá zprávu `$message`, což zpravidla bývá řetězec, a libovolné další parametry. Úkolem je vrátit přeložený řetězec. V Nette není žádná výchozí implementace, můžete si vybrat podle svých potřeb z několika hotových řešeních, které najdete na [Componette |https://componette.org/search/localization]. V jejich dokumentaci se dozvíte, jak translator konfigurovat. Šablonám lze nastavit překladač, který si [necháme předat |dependency-injection:passing-dependencies], metodou `setTranslator()`: @@ -237,7 +355,7 @@ Translator je alternativně možné nastavit pomocí [konfigurace |configuration ```neon latte: extensions: - - Latte\Essential\TranslatorExtension + - Latte\Essential\TranslatorExtension(@Nette\Localization\Translator) ``` Poté lze překladač používat například jako filtr `|translate`, a to včetně doplňujících parametrů, které se předají metodě `translate()` (viz `foo, bar`): diff --git a/application/de/@home.texy b/application/de/@home.texy index 91906d2888..a151863801 100644 --- a/application/de/@home.texy +++ b/application/de/@home.texy @@ -2,35 +2,84 @@ Nette Application ***************** .[perex] -Das Paket `nette/application` ist die Grundlage für die Erstellung interaktiver Webanwendungen. +Nette Application ist der Kern des Nette Frameworks und bietet leistungsstarke Werkzeuge zur Erstellung moderner Webanwendungen. Es bietet eine Reihe außergewöhnlicher Eigenschaften, die die Entwicklung erheblich vereinfachen und die Sicherheit sowie die Wartbarkeit des Codes verbessern. -- [Wie funktionieren die Anwendungen? |how-it-works] -- [Bootstrap] -- [Präsentatoren |Presenters] -- [Schablonen |Templates] -- [Module |Modules] -- [Routing |Routing] -- [URL-Links erstellen |creating-links] -- [Interaktive Komponenten |components] -- [AJAX & Schnipsel |ajax] -- [Multiplikator |multiplier] -- [Konfiguration |Configuration] +Installation +------------ -Einrichtung ------------ - -Laden Sie das Paket herunter und installieren Sie es mit [Composer |best-practices:composer]: +Laden Sie die Bibliothek herunter und installieren Sie sie mit [Composer|best-practices:composer]: ```shell composer require nette/application ``` -| Version | kompatibel mit PHP -|-----------|------------------- -| Nette-Anwendung 4.0 | PHP 8.0 - 8.2 -| Nette Anwendung 3.1 | PHP 7.2 - 8.2 -| Nette Anwendung 3.0 | PHP 7.1 - 8.0 -| Nette-Anwendung 2.4 | PHP 5.6 - 8.0 -Gilt für die neuesten Patch-Versionen. +Warum Nette Application wählen? +------------------------------- + +Nette war schon immer ein Pionier im Bereich der Webtechnologien. + +**Bidirektionaler Router:** Nette verfügt über ein fortschrittliches Routing-System, das durch seine Bidirektionalität einzigartig ist – es übersetzt nicht nur URLs in Anwendungsaktionen, sondern kann auch rückwirkend URL-Adressen generieren. Das bedeutet: +- Sie können jederzeit die URL-Struktur der gesamten Anwendung ändern, ohne die Templates anpassen zu müssen +- URLs werden automatisch kanonisiert, was die SEO verbessert +- Das Routing wird an einer Stelle definiert, nicht verstreut in Annotationen + +**Komponenten und Signale:** Das integrierte Komponentensystem, inspiriert von Delphi und React.js, ist unter PHP-Frameworks völlig einzigartig: +- Ermöglicht die Erstellung wiederverwendbarer UI-Elemente +- Unterstützt die hierarchische Zusammensetzung von Komponenten +- Bietet eine elegante Verarbeitung von AJAX-Anfragen mittels Signalen +- Umfangreiche Bibliothek fertiger Komponenten auf [Componette](https://componette.org) + +**AJAX und Snippets:** Nette führte bereits 2009 eine revolutionäre Methode zur Arbeit mit AJAX ein, lange vor ähnlichen Lösungen wie Hotwire für Ruby on Rails oder Symfony UX Turbo: +- Snippets ermöglichen die Aktualisierung nur von Teilen der Seite, ohne JavaScript schreiben zu müssen +- Automatische Integration mit dem Komponentensystem +- Intelligente Invalidierung von Seitenteilen +- Minimale Menge an übertragenen Daten + +**Intuitive Templates [Latte|latte:]:** Das sicherste Template-System für PHP mit erweiterten Funktionen: +- Automatischer Schutz vor XSS durch kontextsensitives Escaping +- Erweiterbarkeit durch eigene Filter, Funktionen und Tags +- Template-Vererbung und Snippets für AJAX +- Hervorragende Unterstützung für PHP 8.x mit Typsystem + +**Dependency Injection:** Nette nutzt Dependency Injection vollständig aus: +- Automatische Übergabe von Abhängigkeiten (Autowiring) +- Konfiguration mittels übersichtlichem NEON-Format +- Unterstützung für Komponenten-Factories + + +Hauptvorteile +------------- + +- **Sicherheit**: Automatischer Schutz vor [Schwachstellen|nette:vulnerability-protection] wie XSS, CSRF, etc. +- **Produktivität**: Weniger schreiben, mehr Funktionen dank cleverem Design +- **Debugging**: [Tracy Debugger|tracy:] mit Routing-Panel +- **Leistung**: Intelligenter Cache, Lazy Loading von Komponenten +- **Flexibilität**: Einfache Anpassung von URLs auch nach Fertigstellung der Anwendung +- **Komponenten**: Einzigartiges System wiederverwendbarer UI-Elemente +- **Modern**: Volle Unterstützung für PHP 8.4+ und Typsystem + + +Erste Schritte +-------------- + +1. [Wie Anwendungen funktionieren |how-it-works] - Verständnis der grundlegenden Architektur +2. [Presenter |presenters] - Arbeit mit Presentern und Aktionen +3. [Templates |templates] - Erstellung von Templates in Latte +4. [Routing |routing] - Konfiguration von URL-Adressen +5. [Interaktive Komponenten |components] - Nutzung des Komponentensystems + + +PHP-Kompatibilität +------------------ + +| Version | kompatibel mit PHP +|-------------------|------------------- +| Nette Application 4.0 | PHP 8.1 – 8.4 +| Nette Application 3.2 | PHP 8.1 – 8.4 +| Nette Application 3.1 | PHP 7.2 – 8.3 +| Nette Application 3.0 | PHP 7.1 – 8.0 +| Nette Application 2.4 | PHP 5.6 – 8.0 + +Gilt für die letzte Patch-Version. diff --git a/application/de/@left-menu.texy b/application/de/@left-menu.texy index 8fac50f03b..2a16b701bb 100644 --- a/application/de/@left-menu.texy +++ b/application/de/@left-menu.texy @@ -1,19 +1,22 @@ -Nette Bewerbung -*************** -- [Wie funktionieren die Anwendungen? |how-it-works] -- [Bootstrap] -- [Präsentatoren |Presenters] -- [Schablonen |Templates] -- [Module |Modules] -- [Routing |Routing] -- [URL-Links erstellen |creating-links] +Nette Application +***************** +- [Wie Anwendungen funktionieren |how-it-works] +- [Bootstrapping] +- [Presenter |presenters] +- [Templates |templates] +- [Verzeichnisstruktur |directory-structure] +- [Routing |routing] +- [Erstellen von URL-Links |creating-links] - [Interaktive Komponenten |components] -- [AJAX & Schnipsel |ajax] -- [Multiplikator |multiplier] -- [Konfiguration |Configuration] +- [AJAX & Snippets |ajax] +- [Multiplier |Multiplier] +- [Konfiguration |configuration] Weitere Lektüre *************** -- [Bewährte Praktiken |best-practices:] -- [Fehlersuche |nette:troubleshooting] +- [Warum Nette verwenden? |www:10-reasons-why-nette] +- [Installation |nette:installation] +- [Schreiben wir die erste Anwendung! |quickstart:] +- [Anleitungen und Verfahren |best-practices:] +- [Fehlerbehebung |nette:troubleshooting] diff --git a/application/de/@meta.texy b/application/de/@meta.texy new file mode 100644 index 0000000000..b3b806b2ca --- /dev/null +++ b/application/de/@meta.texy @@ -0,0 +1 @@ +{{sitename: Nette Dokumentation}} diff --git a/application/de/ajax.texy b/application/de/ajax.texy index bcdbd4ac93..3ef05ebfe4 100644 --- a/application/de/ajax.texy +++ b/application/de/ajax.texy @@ -1,38 +1,45 @@ -AJAX & Schnipsel -**************** +AJAX & Snippets +***************Hello ...
+Hallo ...
{/snippet} ``` -Wenn Sie ein Snippet mit einem anderen Element erstellen möchten als `Hello ...
+Hallo ...
-
- {foreach $list as $id => $item}
-
- {$item} update - {/foreach} -
-
+ {foreach $items as $id => $item}
+
- {$item} + {/foreach} +
-
- {foreach $list as $id => $item}
-
- {$item} update - {/foreach} -